home *** CD-ROM | disk | FTP | other *** search
/ Practical Internet 2002 February / Practical Internet February 2002.iso / pc / Software / Browsing / httrack-3.09e2.exe / {app} / src / htscore.c < prev    next >
Encoding:
C/C++ Source or Header  |  2001-11-07  |  136.2 KB  |  3,910 lines

  1. /* ------------------------------------------------------------ */
  2. /*
  3. HTTrack Website Copier, Offline Browser for Windows and Unix
  4. Copyright (C) Xavier Roche and other contributors
  5.  
  6. This program is free software; you can redistribute it and/or
  7. modify it under the terms of the GNU General Public License
  8. as published by the Free Software Foundation; either version 2
  9. of the License, or any later version.
  10.  
  11. This program is distributed in the hope that it will be useful,
  12. but WITHOUT ANY WARRANTY; without even the implied warranty of
  13. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  14. GNU General Public License for more details.
  15.  
  16. You should have received a copy of the GNU General Public License
  17. along with this program; if not, write to the Free Software
  18. Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
  19.  
  20.  
  21. Important notes:
  22.  
  23. - We hereby ask people using this source NOT to use it in purpose of grabbing
  24. emails addresses, or collecting any other private information on persons.
  25. This would disgrace our work, and spoil the many hours we spent on it.
  26.  
  27.  
  28. Please visit our Website: http://www.httrack.com
  29. */
  30.  
  31.  
  32. /* ------------------------------------------------------------ */
  33. /* File: Main source                                            */
  34. /* Author: Xavier Roche                                         */
  35. /* ------------------------------------------------------------ */
  36.  
  37. #include "htscore.h"
  38.  
  39. /* specific definitions */
  40. #include "htsbase.h"
  41. #include "htsnet.h"
  42. #include "htsbauth.h"
  43. #include "htsmd5.h"
  44. #include "htsindex.h"
  45. #include <stdio.h>
  46. #include <stdlib.h>
  47. #include <string.h>
  48. #include <time.h>
  49. #include <fcntl.h>
  50. #include <ctype.h>
  51. // htswrap_add
  52. #include "htswrap.h"
  53. /* END specific definitions */
  54.  
  55.  
  56. /* HTML parsing */
  57. #if HTS_ANALYSTE
  58.  
  59. t_hts_htmlcheck_init    hts_htmlcheck_init;
  60. t_hts_htmlcheck_uninit  hts_htmlcheck_uninit;
  61. t_hts_htmlcheck_start   hts_htmlcheck_start;
  62. t_hts_htmlcheck_end     hts_htmlcheck_end;
  63. t_hts_htmlcheck_chopt   hts_htmlcheck_chopt;
  64. t_hts_htmlcheck         hts_htmlcheck;
  65. t_hts_htmlcheck_query   hts_htmlcheck_query;
  66. t_hts_htmlcheck_query2  hts_htmlcheck_query2;
  67. t_hts_htmlcheck_query3  hts_htmlcheck_query3;
  68. t_hts_htmlcheck_loop    hts_htmlcheck_loop;
  69. t_hts_htmlcheck_check   hts_htmlcheck_check;
  70. t_hts_htmlcheck_pause   hts_htmlcheck_pause;
  71. t_hts_htmlcheck_filesave       hts_htmlcheck_filesave;
  72. t_hts_htmlcheck_linkdetected   hts_htmlcheck_linkdetected;
  73. t_hts_htmlcheck_xfrstatus hts_htmlcheck_xfrstatus;
  74.  
  75. char _hts_errmsg[1100]="";
  76. int _hts_in_html_parsing=0;
  77. int _hts_in_html_done=0;  // % done
  78. int _hts_in_html_poll=0;  // parsing
  79. int _hts_setpause=0;
  80. //httrackp* _hts_setopt=NULL;
  81. char** _hts_addurl=NULL;
  82.  
  83. //
  84. int _hts_cancel=0;
  85. #endif
  86.  
  87.  
  88.  
  89. int exit_xh;          /* quick exit (fatal error or interrupt) */
  90.  
  91. /* debug */
  92. #if DEBUG_SHOWTYPES
  93. char REG[32768]="\n";
  94. #endif
  95. #if NSDEBUG
  96. int nsocDEBUG=0;
  97. #endif
  98.  
  99. //
  100. #define _CLRSCR printf("\33[m\33[2J");
  101. #define _GOTOXY(X,Y) printf("\33[" X ";" Y "f");
  102.  
  103. #if DEBUG_CHECKINT
  104.  #define _CHECKINT_FAIL(a) printf("\n%s\n",a); fflush(stdout); exit(1);
  105.  #define _CHECKINT(obj_ptr,message) \
  106.    if (obj_ptr) {\
  107.      if (( * ((char*) (obj_ptr)) != 0) || ( * ((char*) (((char*) (obj_ptr)) + sizeof(*(obj_ptr))-1)) != 0)) {\
  108.        char msg[1100];\
  109.        if (( * ((char*) (obj_ptr)) != 0) && ( * ((char*) (((char*) (obj_ptr)) + sizeof(*(obj_ptr))-1)) != 0))\
  110.          sprintf(msg,"* PANIC: Integrity error (structure crushed)  in: %s",message);\
  111.        else if ( * ((char*) (obj_ptr)) != 0)\
  112.          sprintf(msg,"* PANIC: Integrity error (start of structure) in: %s",message);\
  113.        else\
  114.          sprintf(msg,"* PANIC: Integrity error (end of structure)   in: %s",message);\
  115.        _CHECKINT_FAIL(msg);\
  116.      }\
  117.    } else {\
  118.      char msg[1100];\
  119.      sprintf(msg,"* PANIC: NULL pointer in: %s",message);\
  120.      _CHECKINT_FAIL(msg);\
  121.    }
  122. #endif
  123.  
  124. #if DEBUG_HASH
  125.   // longest hash chain?
  126.   int longest_hash[3]={0,0,0},hashnumber=0;
  127. #endif
  128.  
  129. // demande d'interaction avec le shell
  130. #if HTS_ANALYSTE
  131. char HTbuff[2048];
  132. #endif
  133.  
  134.  
  135.  
  136. // DΘbut de httpmirror, routines annexes
  137.  
  138. // version 1 pour httpmirror
  139. // flusher si on doit lire peu α peu le fichier
  140. #define test_flush if (opt.flush) { fflush(opt.log); fflush(opt.errlog); }
  141.  
  142. // pour allΘger la syntaxe, des raccourcis sont crΘΘs
  143. #define urladr   (liens[ptr]->adr)
  144. #define urlfil   (liens[ptr]->fil)
  145. #define savename (liens[ptr]->sav)
  146. //#define level    (liens[ptr]->depth)
  147.  
  148. // au cas o∙ nous devons quitter rapidement xhttpmirror (plus de mΘmoire, etc)
  149. // note: partir de liens_max.. vers 0.. sinon erreur de violation de mΘmoire: les liens suivants
  150. // ne sont plus α nous.. agh! [dur celui-lα]
  151. #if HTS_ANALYSTE
  152. #define HTMLCHECK_UNINIT { \
  153. if ( (opt.debug>0) && (opt.log!=NULL) ) { \
  154. fspc(opt.log,"info"); fprintf(opt.log,"engine: end"LF); \
  155. } \
  156. hts_htmlcheck_end(); \
  157. }
  158. #else
  159.  #define HTMLCHECK_UNINIT 
  160. #endif
  161.  
  162. #define XH_extuninit { \
  163.   int i; \
  164.   HTMLCHECK_UNINIT \
  165.   if (liens!=NULL) { \
  166.   for(i=lien_max-1;i>=0;i--) { \
  167.   if (liens[i]) { \
  168.   if (liens[i]->firstblock==1) { \
  169.   freet(liens[i]); \
  170.   liens[i]=NULL; \
  171.   } \
  172.   } \
  173.   } \
  174.   freet(liens); \
  175.   liens=NULL; \
  176.   } \
  177.   if (filters[0]) { \
  178.   freet(filters[0]); filters[0]=NULL; \
  179.   } \
  180.   if (back) { \
  181.   int i; \
  182.   for(i=0;i<back_max;i++) { \
  183.   back_delete(back,i); \
  184.   } \
  185.   freet(back); back=NULL;  \
  186.   } \
  187.   checkrobots_free(&robots);\
  188.   if (cache.use) { freet(cache.use); cache.use=NULL; } \
  189.   if (cache.dat) { fclose(cache.dat); cache.dat=NULL; }  \
  190.   if (cache.ndx) { fclose(cache.ndx); cache.ndx=NULL; } \
  191.   if (cache.olddat) { fclose(cache.olddat); cache.olddat=NULL; } \
  192.   if (cache.lst) { fclose(cache.lst); cache.lst=NULL; } \
  193.   if (opt.log) fflush(opt.log); \
  194.   if (opt.errlog) fflush(opt.errlog);\
  195.   if (makestat_fp) { fclose(makestat_fp); makestat_fp=NULL; } \
  196.   if (maketrack_fp){ fclose(maketrack_fp); maketrack_fp=NULL; } \
  197.   if (opt.accept_cookie) cookie_save(opt.cookie,fconcat(opt.path_log,"cookies.txt")); \
  198.   if (makeindex_fp) { fclose(makeindex_fp); makeindex_fp=NULL; } \
  199.   if (cache_hashtable) { inthash_delete(&cache_hashtable); } \
  200.   if (template_header) { freet(template_header); template_header=NULL; } \
  201.   if (template_body)   { freet(template_body); template_body=NULL; } \
  202.   if (template_footer) { freet(template_footer); template_footer=NULL; } \
  203.   structcheck_init(-1); \
  204. }
  205. #define XH_uninit XH_extuninit if (r.adr) { freet(r.adr); r.adr=NULL; } 
  206.  
  207. // Enregistrement d'un lien:
  208. // on calcule la taille nΘcessaire: taille des 3 chaεnes α stocker (taille forcΘe paire, plus 2 octets de sΘcuritΘ)
  209. // puis on vΘrifie qu'on a assez de marge dans le buffer - sinon on en rΘalloue un autre
  210. // enfin on Θcrit α l'adresse courante du buffer, qu'on incrΘmente. on dΘcrΘmente la taille dispo d'autant ensuite
  211. // codebase: si non nul et si .class stockee on le note pour chemin primaire pour classes
  212. // FA,FS: former_adr et former_fil, lien original
  213. #define REALLOC_SIZE 8192
  214. #define HTS_ALIGN 4
  215. #if HTS_HASH
  216. #define liens_record_sav_len(A) 
  217. #else
  218. #define liens_record_sav_len(A) (A)->sav_len=strlen((A)->sav)
  219. #endif
  220.  
  221. #define liens_record(A,F,S,FA,FF) { \
  222. int notecode=0; \
  223. int adr_len=strlen(A),fil_len=strlen(F),sav_len=strlen(S),cod_len=0,former_adr_len=strlen(FA),former_fil_len=strlen(FF); \
  224. if (former_adr_len>0) {\
  225. former_adr_len=(former_adr_len/HTS_ALIGN)*HTS_ALIGN+HTS_ALIGN+4; \
  226. former_fil_len=(former_fil_len/HTS_ALIGN)*HTS_ALIGN+HTS_ALIGN+4; \
  227. } else former_adr_len=former_fil_len=0;\
  228. if (strlen(F)>6) if (strnotempty(codebase)) if (strfield(F+strlen(F)-6,".class")) { notecode=1; \
  229. cod_len=strlen(codebase); cod_len=(cod_len/HTS_ALIGN)*HTS_ALIGN+HTS_ALIGN+4; } \
  230. adr_len=(adr_len/HTS_ALIGN)*HTS_ALIGN+HTS_ALIGN+4; fil_len=(fil_len/HTS_ALIGN)*HTS_ALIGN+HTS_ALIGN+4; sav_len=(sav_len/HTS_ALIGN)*HTS_ALIGN+HTS_ALIGN+4; \
  231. if ((int) lien_size < (int) (adr_len+fil_len+sav_len+cod_len+former_adr_len+former_fil_len+sizeof(lien_url))) { \
  232. lien_buffer=(char*) ((void*) calloct(add_tab_alloc,1)); \
  233. lien_size=add_tab_alloc; \
  234. if (lien_buffer!=NULL) { \
  235. liens[lien_tot]=(lien_url*) (void*) lien_buffer; lien_buffer+=sizeof(lien_url); lien_size-=sizeof(lien_url); \
  236. liens[lien_tot]->firstblock=1; \
  237. } \
  238. } else { \
  239. liens[lien_tot]=(lien_url*) (void*) lien_buffer; lien_buffer+=sizeof(lien_url); lien_size-=sizeof(lien_url); \
  240. liens[lien_tot]->firstblock=0; \
  241. } \
  242. if (liens[lien_tot]!=NULL) { \
  243. liens[lien_tot]->adr=lien_buffer; lien_buffer+=adr_len; lien_size-=adr_len; \
  244. liens[lien_tot]->fil=lien_buffer; lien_buffer+=fil_len; lien_size-=fil_len; \
  245. liens[lien_tot]->sav=lien_buffer; lien_buffer+=sav_len; lien_size-=sav_len; \
  246. liens[lien_tot]->cod=NULL; \
  247. if (notecode) { liens[lien_tot]->cod=lien_buffer; lien_buffer+=cod_len; lien_size-=cod_len; strcpy(liens[lien_tot]->cod,codebase); } \
  248. if (former_adr_len>0) {\
  249. liens[lien_tot]->former_adr=lien_buffer; lien_buffer+=former_adr_len; lien_size-=former_adr_len; \
  250. liens[lien_tot]->former_fil=lien_buffer; lien_buffer+=former_fil_len; lien_size-=former_fil_len; \
  251. strcpy(liens[lien_tot]->former_adr,FA); \
  252. strcpy(liens[lien_tot]->former_fil,FF); \
  253. }\
  254. strcpy(liens[lien_tot]->adr,A); \
  255. strcpy(liens[lien_tot]->fil,F); \
  256. strcpy(liens[lien_tot]->sav,S); \
  257. liens_record_sav_len(liens[lien_tot]); \
  258. hash_write(&hash,lien_tot);  \
  259. } \
  260. }
  261.  
  262. /* - abandonnΘ (simplifie) -
  263. // Ajouter α un lien EXISTANT deux champs former_adr et former_fil pour indiquer le nom d'un fichier avant un "move"
  264. // NOTE: si un alloc est fait ici il n'y aura pas de freet() α la fin, tant pis (firstbloc)
  265. #define liens_add_former(index,A,F) { \
  266. int adr_len=strlen(A),fil_len=strlen(F); \
  267. adr_len=(adr_len/HTS_ALIGN)*HTS_ALIGN+HTS_ALIGN+4; fil_len=(fil_len/HTS_ALIGN)*HTS_ALIGN+HTS_ALIGN+4; \
  268. if ((int) lien_size < (int) (adr_len+fil_len)) { \
  269. lien_buffer=(char*) calloct(add_tab_alloc,1); \
  270. lien_size=add_tab_alloc; \
  271. } \
  272. if (lien_buffer!=NULL) { \
  273. if (liens[lien_tot]!=NULL) { \
  274. liens[lien_tot]->former_adr=lien_buffer; lien_buffer+=adr_len; lien_size-=adr_len; \
  275. liens[lien_tot]->former_fil=lien_buffer; lien_buffer+=fil_len; lien_size-=fil_len; \
  276. strcpy(liens[lien_tot]->former_adr,A); \
  277. strcpy(liens[lien_tot]->former_fil,F); \
  278. } \
  279. } \
  280. }
  281. */
  282.  
  283. #if 0
  284. #define HT_ADD_ADR { \
  285.   fwrite(lastsaved,1,((int) adr)- ((int) lastsaved),fp); \
  286.   lastsaved=adr; }
  287. #define HT_ADD(A) fwrite(A,1,(int) strlen(A),fp);
  288. #define HT_ADD_START
  289. #define HT_ADD_END if (fp) { fclose(fp); fp=NULL; }
  290. #define HT_ADD_FOP { \
  291.   fp=filecreate(savename); \
  292.   if (fp==NULL) { \
  293.   if (opt.errlog) { \
  294.   fspc(opt.errlog,"error"); fprintf(opt.errlog,"Unable to create %s for %s%s"LF,savename,urladr,urlfil); \
  295.   test_flush; \
  296.   } \
  297.   freet(r.adr); r.adr=NULL; \
  298.   error=1; \
  299.   } \
  300.   }
  301. #else
  302. // version optimisΘe, qui permet de ne pas toucher aux html non modifiΘs (update)
  303. #define HT_ADD_CHK(A) if (((int) A+ht_len+1)>ht_size) { \
  304.   ht_size=A+ht_len+REALLOC_SIZE; \
  305.   ht_buff=(char*) realloct(ht_buff,ht_size); \
  306.   if (ht_buff==NULL) { \
  307.   printf("PANIC! : Not enough memory [%d]\n",__LINE__); \
  308.   XH_uninit; \
  309.   } \
  310.   } \
  311.   ht_len+=A;
  312. /*
  313. (Optimized)
  314. #define HT_ADD_ADR { int i,j=ht_len; HT_ADD_CHK(((int) adr)- ((int) lastsaved)) \
  315.   for(i=0;i<((int) adr)- ((int) lastsaved);i++) \
  316.   ht_buff[j+i]=lastsaved[i]; \
  317.   ht_buff[j+((int) adr)- ((int) lastsaved)]='\0'; \
  318.   lastsaved=adr; }
  319. */
  320. #define HT_ADD_ADR { int i=((int) adr)- ((int) lastsaved),j=ht_len; HT_ADD_CHK(i) \
  321.   bcopy(lastsaved,ht_buff+j,i); \
  322.   ht_buff[j+i]='\0'; \
  323.   lastsaved=adr; }
  324. /*
  325. (Optimized)
  326. #define HT_ADD(A) { HT_ADD_CHK(strlen(A)) strcat(ht_buff,A); }
  327. */
  328. #define HT_ADD(A) { int i=strlen(A),j=ht_len; \
  329.   if (i) { \
  330.   HT_ADD_CHK(i) \
  331.   bcopy(A,ht_buff+j,i); \
  332.   ht_buff[j+i]='\0'; \
  333.   } }
  334. #define HT_ADD_START \
  335.   int ht_size=(int)(r.size*5)/4+REALLOC_SIZE; \
  336.   int ht_len=0; \
  337.   char* ht_buff=NULL; \
  338.   if ((opt.getmode & 1) && (ptr>0)) { \
  339.   ht_buff=(char*) malloct(ht_size); \
  340.   if (ht_buff==NULL) { \
  341.   printf("PANIC! : Not enough memory [%d]\n",__LINE__); \
  342.   XH_uninit; \
  343.   } \
  344.   ht_buff[0]='\0'; \
  345.   }
  346. #define HT_ADD_END { \
  347.   int ok=0;\
  348.   if (ht_buff) { \
  349.   int file_len=(int) strlen(ht_buff);\
  350.   char digest[32+2];\
  351.   digest[0]='\0';\
  352.   domd5mem(ht_buff,file_len,digest,1,0);\
  353.   if (fsize(antislash(savename))==file_len) { \
  354.   int mlen;\
  355.   char* mbuff;\
  356.   cache_readdata(&cache,"//[HTML-MD5]//",savename,&mbuff,&mlen);\
  357.   if (mlen) mbuff[mlen]='\0';\
  358.   if ((mlen == 32) && (strcmp(((mbuff!=NULL)?mbuff:""),digest)==0)) {\
  359.   ok=1;\
  360.   if ( (opt.debug>1) && (opt.log!=NULL) ) {\
  361.   fspc(opt.log,"debug"); fprintf(opt.log,"File not re-written (md5): %s"LF,savename);\
  362.   test_flush;\
  363.   }\
  364.   } else {\
  365.   ok=0;\
  366.   } \
  367.   }\
  368.   if (!ok) { \
  369.   fp=filecreate(savename); \
  370.   if (fp) { \
  371.   if ((int)fwrite(ht_buff,1,file_len,fp) != file_len) { \
  372.   if (opt.errlog) {   \
  373.   fspc(opt.errlog,"error"); fprintf(opt.errlog,"Unable to write HTML file %s"LF,savename);\
  374.   test_flush;\
  375.   }\
  376.   }\
  377.   fclose(fp); fp=NULL; \
  378.   if (strnotempty(r.lastmodified)) \
  379.   set_filetime_rfc822(savename,r.lastmodified); \
  380.   usercommand(0,NULL,antislash(savename)); \
  381.   } else {\
  382.   if (opt.errlog) { \
  383.   fspc(opt.errlog,"error");\
  384.   fprintf(opt.errlog,"Unable to save file %s"LF,savename);\
  385.   test_flush;\
  386.   }\
  387.   }\
  388.   } else {\
  389.   filenote(savename,NULL); \
  390.   }\
  391.   if (cache.ndx)\
  392.     cache_writedata(cache.ndx,cache.dat,"//[HTML-MD5]//",savename,digest,(int)strlen(digest));\
  393.   } \
  394.   freet(ht_buff); ht_buff=NULL; \
  395.   }
  396. #define HT_ADD_FOP 
  397. #endif
  398.  
  399. // libΘrer filters[0] pour insΘrer un ΘlΘment dans filters[0]
  400. #define HT_INSERT_FILTERS0 {\
  401.   int i;\
  402.   if (filptr>0) {\
  403.     for(i=filptr-1;i>=0;i--) {\
  404.       strcpy(filters[i+1],filters[i]);\
  405.     }\
  406.   }\
  407.   strcpy(filters[0],"");\
  408.   filptr++;\
  409.   filptr=minimum(filptr,filter_max);\
  410. }
  411.  
  412. // DΘbut de httpmirror, robot
  413. // url1 peut Ωtre multiple
  414. int httpmirror(char* url1,httrackp opt) {
  415.   char* primary=NULL;          // premiΦre page, contenant les liens α scanner
  416.   int lien_tot=0;              // nombre de liens pour le moment
  417.   lien_url** liens=NULL;       // les pointeurs sur les liens
  418.   hash_struct hash;            // systΦme de hachage, accΘlΦre la recherche dans les liens
  419.   t_cookie cookie;             // gestion des cookies
  420.   int lien_max=0;
  421.   int lien_size=0;        // octets restants dans buffer liens dispo
  422.   char* lien_buffer=NULL; // buffer liens actuel
  423.   int add_tab_alloc=256000;    // +256K de liens α chaque fois
  424.   //char* tab_alloc=NULL;
  425.   int ptr;             // pointeur actuel sur les liens
  426.   //
  427.   int numero_passe=0;  // deux passes pour html puis images
  428.   int back_max=0;      // fichiers qui peuvent Ωtre en local
  429.   lien_back* back=NULL; // backing en local
  430.   htsblk r;            // retour de certaines fonctions
  431.   TStamp lastime=0;    // pour affichage infos de tmp en tmp
  432.   // pour les stats, nombre de fichiers & octets Θcrits
  433.   LLint stat_fragment=0;  // pour la fragmentation
  434.   //TStamp istat_timestart;   // dΘpart pour calcul instantannΘ
  435.   //
  436.   TStamp last_info_shell=0;
  437.   int info_shell=0;
  438.   // note: α amΘliorer // **
  439.   char* filters[HTS_FILTERSMAX];
  440.   int filter_max=0;
  441.   int filptr=0;
  442.   //
  443.   int makeindex_done=0;  // lorsque l'index sera fait
  444.   FILE* makeindex_fp=NULL;
  445.   int makeindex_links=0;
  446.   char makeindex_firstlink[HTS_URLMAXSIZE*2];
  447.   // statistiques (mode #Z)
  448.   FILE* makestat_fp=NULL;    // fichier de stats taux transfert
  449.   FILE* maketrack_fp=NULL;   // idem pour le tracking
  450.   TStamp makestat_time=0;    // attente (secondes)
  451.   LLint makestat_total=0;    // repΦre du nombre d'octets transfΘrΘs depuis denriΦre stat
  452.   int makestat_lnk=0;        // idem, pour le nombre de liens
  453.   //
  454.   char codebase[HTS_URLMAXSIZE*2];  // base pour applet java
  455.   char base[HTS_URLMAXSIZE*2];      // base pour les autres fichiers
  456.   //
  457.   cache_back cache;
  458.   robots_wizard robots;    // gestion robots.txt
  459.   inthash cache_hashtable=NULL;
  460.   int cache_hash_size=0;
  461.   //
  462.   char *template_header=NULL,*template_body=NULL,*template_footer=NULL;
  463.   //
  464.   codebase[0]='\0'; base[0]='\0';
  465.   //
  466.   cookie.auth.next=NULL;
  467.   cookie.auth.auth[0]=cookie.auth.prefix[0]='\0';
  468.   //
  469.  
  470.   // noter heure actuelle de dΘpart en secondes
  471.   bzero((char *)&HTS_STAT, sizeof(HTS_STAT));
  472.   HTS_STAT.stat_timestart=time_local();
  473.   //istat_timestart=stat_timestart;
  474.   HTS_STAT.istat_timestart[0]=HTS_STAT.istat_timestart[1]=mtime_local();
  475.   /* reset stats */
  476.   HTS_STAT.HTS_TOTAL_RECV=0;
  477.   HTS_STAT.istat_bytes[0]=HTS_STAT.istat_bytes[1]=0;
  478.   if (opt.aff_progress)
  479.     lastime=HTS_STAT.stat_timestart;
  480.   if (opt.shell) {
  481.     last_info_shell=HTS_STAT.stat_timestart;
  482.   }
  483.   if ((opt.makestat) || (opt.maketrack)){
  484.     makestat_time=HTS_STAT.stat_timestart;
  485.   }
  486.   // initialiser compteur erreurs
  487.   fspc(NULL,NULL);
  488.  
  489.   // initialiser cookie
  490.   if (opt.accept_cookie) {
  491.     opt.cookie=&cookie;
  492.     cookie.max_len=30000;       // max len
  493.     strcpy(cookie.data,"");
  494.     // Charger cookies.txt par dΘfaut ou cookies.txt du miroir
  495.     if (fexist(fconcat(opt.path_log,"cookies.txt")))
  496.       cookie_load(opt.cookie,opt.path_log,"cookies.txt");
  497.     else if (fexist("cookies.txt"))
  498.       cookie_load(opt.cookie,"","cookies.txt");
  499.   } else
  500.     opt.cookie=NULL;
  501.  
  502.   // initialiser exit_xh
  503.   exit_xh=0;          // sortir prΘmaturΘment (var globale)
  504.  
  505.   // initialiser usercommand
  506.   usercommand(opt.sys_com_exec,opt.sys_com,"");
  507.  
  508.   // initialiser structcheck
  509.   structcheck_init(1);
  510.  
  511.   // initialiser tableau options accessible par d'autres fonctions (signal)
  512.   hts_declareoptbuffer(&opt);
  513.  
  514.   // initialiser verif_backblue
  515.   verif_backblue(NULL);
  516.   verif_external(0,0);
  517.   verif_external(1,0);
  518.  
  519.   // et templates html
  520.   template_header=readfile_or(fconcat(opt.path_bin,"httrack/index-header.html"),HTS_INDEX_HEADER);
  521.   template_body=readfile_or(fconcat(opt.path_bin,"httrack/index-body.html"),HTS_INDEX_BODY);
  522.   template_footer=readfile_or(fconcat(opt.path_bin,"httrack/index-footer.html"),HTS_INDEX_FOOTER);
  523.  
  524.   // initialiser mimedefs
  525.   get_userhttptype(1,opt.mimedefs,NULL);
  526.  
  527.   // Initialiser indexation
  528.   if (opt.kindex)
  529.     index_init(opt.path_html);
  530.  
  531.   // effacer bloc cache
  532.   bzero((char *)&cache, sizeof(cache_back));
  533.   cache.type=opt.cache;  // cache?
  534.   cache.errlog=opt.errlog;  // err log?
  535.   cache.ptr_ant=cache.ptr_last=0;   // pointeur pour anticiper
  536.  
  537.   // initialiser hash cache
  538.   if (!cache_hash_size) 
  539.     cache_hash_size=HTS_HASH_SIZE;
  540.   cache_hashtable=inthash_new(cache_hash_size);
  541.   if (cache_hashtable==NULL) {
  542.     printf("PANIC! : Not enough memory [%d]\n",__LINE__);
  543.     filters[0]=NULL; back_max=0;    // uniquement a cause du warning de XH_extuninit
  544.     XH_extuninit;
  545.     return 0;
  546.   }
  547.   cache.hashtable=(void*)cache_hashtable;      /* copy backcache hash */
  548.  
  549.   // initialiser cache DNS
  550.   _hts_lockdns(-999);
  551.  
  552.   // robots.txt
  553.   strcpy(robots.adr,"!");    // dummy
  554.   robots.token[0]='\0';
  555.   robots.next=NULL;          // suivant
  556.   
  557.   // effacer filters
  558.   filter_max=maximum(opt.maxfilter,128);
  559.   filters[0]=(char*) malloct((filter_max+1)*(HTS_URLMAXSIZE*2));
  560.   if (filters[0]==NULL) {
  561.     printf("PANIC! : Not enough memory [%d]\n",__LINE__);
  562.     back_max=0;    // uniquement a cause du warning de XH_extuninit
  563.     XH_extuninit;
  564.     return 0;
  565.   } else {
  566.     int i;
  567.     for(i=0;i<=filter_max;i++) {    // PLUS UN (sΘcuritΘ)
  568.       filters[i]=filters[0]+i*(HTS_URLMAXSIZE*2);
  569.       filters[i][0]='\0';
  570.     }
  571.   }
  572.   opt.filters.filptr=&filptr;
  573.   opt.filters.filter_max=&filter_max;
  574.   opt.filters.filters=filters;
  575.  
  576.   // tableau de pointeurs sur les liens
  577.   lien_max=maximum(opt.maxlink,32);
  578.   liens=(lien_url**) malloct(lien_max*sizeof(lien_url*));   // tableau de pointeurs sur les liens
  579.   if (liens==NULL) {
  580.     printf("PANIC! : Not enough memory [%d]\n",__LINE__);
  581.     //XH_uninit;
  582.     return 0;
  583.   } else {
  584.     int i;
  585.     for(i=0;i<lien_max;i++) {
  586.       liens[i]=NULL;     
  587.     }
  588.   }
  589.   // initialiser ptr et lien_tot
  590.   ptr=0;
  591.   lien_tot=0;
  592. #if HTS_HASH
  593.   // initialiser hachage
  594.   {
  595.     int i;
  596.     for(i=0;i<HTS_HASH_SIZE;i++)
  597.       hash.hash[0][i]=hash.hash[1][i]=hash.hash[2][i] = -1;    // pas d'entrΘes
  598.     hash.liens = liens;
  599.     hash.max_lien=0;
  600.   }
  601. #endif
  602.  
  603.   
  604.   // copier adresse(s) dans liste des adresses
  605.   {
  606.     char *a=url1;
  607.     int primary_len=8192;
  608.     if (strnotempty(opt.filelist)) {
  609.       primary_len+=max(0,fsize(opt.filelist)*2);
  610.     }
  611.     primary_len+=strlen(url1)*2;
  612.  
  613.     // crΘation de la premiΦre page, qui contient les liens de base α scanner
  614.     // c'est plus propre et plus logique que d'entrer α la main les liens dans la pile
  615.     // on bΘnΘficie ainsi des vΘrifications et des tests du robot pour les liens "primaires"
  616.     primary=(char*) malloct(primary_len); 
  617.     if (primary) {
  618.       primary[0]='\0';
  619.     } else {
  620.       printf("PANIC! : Not enough memory [%d]\n",__LINE__);
  621.       back_max=0;    // uniquement a cause du warning de XH_extuninit
  622.       XH_extuninit;
  623.       return 0;
  624.     }
  625.     
  626.     while(*a) {
  627.       int i;
  628.       int joker=0;
  629.  
  630.       // vΘrifier qu'il n'y a pas de * dans l'url
  631.       if (*a=='+')
  632.         joker=1;
  633.       else if (*a=='-')
  634.         joker=1;
  635.       /* NON, certaines URL ont des * (!)
  636.       else {
  637.         int i=0;
  638.         while((a[i]!=0) && (a[i]!=' ')) if (a[i++]=='*') joker=1;
  639.       }
  640.       */
  641.       
  642.       if (joker) {    // joker ou filters
  643.         //char* p;
  644.         char tempo[HTS_URLMAXSIZE*2];
  645.         int type; int plus=0;
  646.  
  647.         // noter joker (dans b)
  648.         if (*a=='+') {  // champ +
  649.           type=1; plus=1; a++;
  650.         } else if (*a=='-') {  // champ forbidden[]
  651.           type=0; a++;
  652.         } else {  // champ + avec joker sans doute
  653.           type=1;
  654.         }
  655.  
  656.         // recopier prochaine chaine (+ ou -)
  657.         i=0;
  658.         while((*a!=0) && (*a!=' ')) { tempo[i++]=*a; a++; }  
  659.         tempo[i++]='\0';
  660.         while(*a==' ') { a++; }
  661.  
  662.         // sauter les + sans rien aprΦs..
  663.         if (strnotempty(tempo)) {
  664.           if ((plus==0) && (type==1)) {  // implicite: *www.edf.fr par exemple
  665.             if (tempo[strlen(tempo)-1]!='*') {
  666.               strcat(tempo,"*");  // ajouter un *
  667.             }
  668.           }
  669.           if (type)
  670.             strcpy(filters[filptr],"+");
  671.           else
  672.             strcpy(filters[filptr],"-");
  673.           if (strfield(tempo,"http://"))
  674.             strcat(filters[filptr],tempo+7);        // ignorer http://
  675.           else if (strfield(tempo,"ftp://"))
  676.             strcat(filters[filptr],tempo+6);        // ignorer ftp://
  677.           else
  678.             strcat(filters[filptr],tempo);
  679.           filptr++;          
  680.         }
  681.         
  682.       } else {    // adresse normale
  683.         char url[HTS_URLMAXSIZE*2];
  684.         // prochaine adresse
  685.         i=0;
  686.         while((*a!=0) && (*a!=' ')) { url[i++]=*a; a++; }  
  687.         while(*a==' ') { a++; }
  688.         url[i++]='\0';
  689.  
  690.         //strcat(primary,"<PRIMARY=\"");
  691.         if (strstr(url,":/")==NULL)
  692.           strcat(primary,"http://");
  693.         strcat(primary,url);
  694.         //strcat(primary,"\">");
  695.         strcat(primary,"\n");
  696.       }
  697.     }  // while
  698.  
  699.     /* load URL file list */
  700.     /* OPTIMIZED for fast load */
  701.     if (strnotempty(opt.filelist)) {
  702.       char* filelist_buff=NULL;
  703.       int filelist_sz=fsize(opt.filelist);
  704.       if (filelist_sz>0) {
  705.         FILE* fp=fopen(opt.filelist,"rb");
  706.         if (fp) {
  707.           filelist_buff=malloct(filelist_sz);
  708.           if (filelist_buff) {
  709.             if ((int)fread(filelist_buff,1,filelist_sz,fp) != filelist_sz) {
  710.               freet(filelist_buff);
  711.               filelist_buff=NULL;
  712.             }
  713.           }
  714.           fclose(fp);
  715.         }
  716.       }
  717.       
  718.       if (filelist_buff) {
  719.         int filelist_ptr=0;
  720.         int n=0;
  721.         char line[HTS_URLMAXSIZE*2];
  722.         char* primary_ptr = primary + strlen(primary);
  723.         while( filelist_ptr < filelist_sz ) {
  724.           int count=binput(filelist_buff+filelist_ptr,line,HTS_URLMAXSIZE);
  725.           int line_size;
  726.           filelist_ptr+=count;
  727.           if (count) {
  728.             n++;
  729.             if (strstr(line,":/")==NULL) {
  730.               bcopy("http://",primary_ptr,7);
  731.               primary_ptr+=7;
  732.             }
  733.             line_size=strlen(line);
  734.             bcopy(line,primary_ptr,line_size);
  735.             primary_ptr+=line_size;
  736.             *(primary_ptr++)='\n';
  737.           }
  738.         }
  739.         *(primary_ptr++)='\0';
  740.         // fclose(fp);
  741.         if (opt.log!=NULL) {
  742.           fspc(opt.log,"info"); fprintf(opt.log,"%d links added from %s"LF,n,opt.filelist); test_flush;
  743.         }
  744.  
  745.         // Free buffer
  746.         freet(filelist_buff);
  747.       } else {
  748.         if (opt.errlog!=NULL) {
  749.           fspc(opt.errlog,"error"); fprintf(opt.errlog,"Could not include URL list: %s"LF,opt.filelist); test_flush;
  750.         }
  751.       }
  752.     }
  753.  
  754.  
  755.     // lien primaire
  756.     liens_record("primary","/primary","primary.html","","");
  757.     if (liens[lien_tot]==NULL) {  // erreur, pas de place rΘservΘe
  758.       printf("PANIC! : Not enough memory [%d]\n",__LINE__);
  759.       if (opt.errlog) {
  760.         fprintf(opt.errlog,"Not enough memory, can not re-allocate %d bytes"LF,(add_tab_alloc+1)*sizeof(lien_url));
  761.         test_flush;
  762.       }
  763.       back_max=0;    // uniquement a cause du warning de XH_extuninit
  764.       XH_extuninit;    // dΘsallocation mΘmoire & buffers
  765.       return 0;
  766.     }    
  767.     liens[lien_tot]->testmode=0;          // pas mode test
  768.     liens[lien_tot]->link_import=0;       // pas mode import
  769.     liens[lien_tot]->depth=opt.depth+1;   // lien de prioritΘ maximale
  770.     liens[lien_tot]->pass2=0;             // 1Φre passe
  771.     liens[lien_tot]->retry=opt.retry;     // lien de prioritΘ maximale
  772.     liens[lien_tot]->premier=lien_tot;    // premier lien, objet-pΦre=objet              
  773.     liens[lien_tot]->precedent=lien_tot;  // lien prΘcΘdent
  774.     lien_tot++;  
  775.  
  776.     // Initialiser cache
  777.     cache_init(&cache,&opt);
  778.   }
  779.   
  780. #if BDEBUG==3
  781.   {
  782.     int i;
  783.     for(i=0;i<lien_tot;i++) {
  784.       printf("%d>%s%s as %s\n",i,liens[i]->adr,liens[i]->fil,liens[i]->sav);
  785.     }
  786.     for(i=0;i<filptr;i++) {
  787.       printf("%d>filters=%s\n",i,filters[i]);
  788.     }
  789.   }
  790. #endif
  791.    
  792.   // backing
  793.   //soc_max=opt.maxsoc;
  794.   if (opt.maxsoc>0) {
  795. #if BDEBUG==2
  796.     _CLRSCR;
  797. #endif
  798.     // Nombre de fichiers HTML pouvant Ωtre prΘsents en mΘmoire de maniΦre simultannΘe
  799.     // On prΘvoit large: les fichiers HTML ne prennent que peu de place en mΘmoire, et les
  800.     // fichiers non html sont sauvΘs en direct sur disque.
  801.     // --> 1024 entrΘes + 32 entrΘes par socket en supplΘment
  802.     back_max=opt.maxsoc*32+1024;
  803.     //back_max=opt.maxsoc*8+32;
  804.     back=(lien_back*) calloct((back_max+1),sizeof(lien_back));
  805.     if (back==NULL) {
  806.       if (opt.errlog)
  807.         fprintf(opt.errlog,"Not enough memory, can not allocate %d bytes"LF,(opt.maxsoc+1)*sizeof(lien_back));
  808.       return 0;
  809.     } else {    // copier buffer-location & effacer
  810.       int i;
  811.       for(i=0;i<back_max;i++){
  812.         back[i].r.location=back[i].location_buffer;
  813.         back[i].status=-1;
  814.         back[i].r.soc=INVALID_SOCKET;
  815.       }
  816.     }
  817.   }
  818.  
  819.  
  820.   // flush
  821.   test_flush;
  822.  
  823.   // statistiques
  824.   if (opt.makestat) {
  825.     makestat_fp=fopen(fconcat(opt.path_log,"hts-stats.txt"),"wb");
  826.     if (makestat_fp != NULL) {
  827.       fprintf(makestat_fp,"HTTrack statistics report, every minutes"LF LF);
  828.     }
  829.   }
  830.  
  831.   // tracking -- dΘbuggage
  832.   if (opt.maketrack) {
  833.     maketrack_fp=fopen(fconcat(opt.path_log,"hts-track.txt"),"wb");
  834.     if (maketrack_fp != NULL) {
  835.       fprintf(maketrack_fp,"HTTrack tracking report, every minutes"LF LF);
  836.     }
  837.   }
  838.  
  839.   // on n'a pas de liens!! (exemple: httrack www.* impossible sans dΘpart..)
  840.   if (lien_tot<=0) {
  841.     if (opt.errlog) {
  842.       fprintf(opt.errlog,"Error! You MUST specify at least one complete URL, and not only wildcards!"LF);
  843.     }
  844.   }
  845.  
  846.  
  847.   // attendre une certaine heure..
  848.   if (opt.waittime>0) {
  849.     int rollover=0;
  850.     int ok=0;
  851.     {
  852.       TStamp tl=0;
  853.       time_t tt;
  854.       struct tm* A;
  855.       tt=time(NULL);
  856.       A=localtime(&tt);
  857.       tl+=A->tm_sec;
  858.       tl+=A->tm_min*60;
  859.       tl+=A->tm_hour*60*60;
  860.       if (tl>opt.waittime)  // attendre minuit
  861.         rollover=1;
  862.     }
  863.  
  864.     // attendre..
  865.     do {
  866.       TStamp tl=0;
  867.       time_t tt;
  868.       struct tm* A;
  869.       tt=time(NULL);
  870.       A=localtime(&tt);
  871.       tl+=A->tm_sec;
  872.       tl+=A->tm_min*60;
  873.       tl+=A->tm_hour*60*60;
  874.  
  875.       if (rollover) {
  876.         if (tl<=opt.waittime)
  877.           rollover=0;  // attendre heure
  878.       } else {
  879.         if (tl>opt.waittime)
  880.           ok=1;  // ok!
  881.       }
  882.       
  883. #if HTS_ANALYSTE
  884.       {  
  885.         int r;
  886.         if (rollover)
  887.           r=hts_htmlcheck_loop(back,back_max,0,0,lien_tot,(int) (opt.waittime-tl+24*3600),NULL);
  888.         else
  889.           r=hts_htmlcheck_loop(back,back_max,0,0,lien_tot,(int) (opt.waittime-tl),NULL);
  890.         if (!r) {
  891.           exit_xh=1;  // exit requested
  892.           ok=1;          
  893.         } else
  894.           Sleep(100);
  895.       }
  896. #endif
  897.     } while(!ok);    
  898.     
  899.     // note: recopie de plus haut
  900.     // noter heure actuelle de dΘpart en secondes
  901.     HTS_STAT.stat_timestart=time_local();
  902.     if (opt.aff_progress)
  903.       lastime=HTS_STAT.stat_timestart;
  904.     if (opt.shell) {
  905.       last_info_shell=HTS_STAT.stat_timestart;
  906.     }
  907.     if ((opt.makestat) || (opt.maketrack)){
  908.       makestat_time=HTS_STAT.stat_timestart;
  909.     }
  910.  
  911.  
  912.   }  
  913.   /* Info for wrappers */
  914.   if ( (opt.debug>0) && (opt.log!=NULL) ) {
  915.     fspc(opt.log,"info"); fprintf(opt.log,"engine: start"LF);
  916.   }
  917. #if HTS_ANALYSTE
  918.   if (!hts_htmlcheck_start(&opt)) {
  919.     XH_extuninit;
  920.     return 1;
  921.   }
  922. #endif
  923.   
  924.  
  925.   // ------------------------------------------------------------
  926.  
  927.   // ------------------------------------------------------------
  928.   // Boucle gΘnΘrale de parcours des liens
  929.   // ------------------------------------------------------------
  930.   do {
  931.     int error=0;          // si error alors sauter
  932.     int store_errpage=0;  // c'est une erreur mais on enregistre le html
  933.     char loc[HTS_URLMAXSIZE*2];    // adresse de relocation
  934.  
  935.     // Ici on charge le fichier (html, gif..) en mΘmoire
  936.     // Les HTMLs sont traitΘs (si leur prioritΘ est suffisante)
  937.  
  938.     // effacer r
  939.     bzero((char *)&r, sizeof(htsblk)); r.soc=INVALID_SOCKET;
  940.     r.location=loc;    // en cas d'erreur 3xx (moved)
  941.     // recopier proxy
  942.     bcopy((char*) &opt.proxy,(char*) &(r.req.proxy), sizeof(opt.proxy));
  943.     // et user-agent
  944.     strcpy(r.req.user_agent,opt.user_agent);
  945.     r.req.user_agent_send=opt.user_agent_send;
  946.  
  947.     if (!error) {
  948.       
  949.       // Skip empty/invalid/done in background
  950.       if (liens[ptr]) {
  951.         while (  (liens[ptr]) && (
  952.                     ( ((urladr != NULL)?(urladr):(" "))[0]=='!') ||
  953.                     ( ((urlfil != NULL)?(urlfil):(" "))[0]=='\0') ||
  954.                     ( (liens[ptr]->pass2 == -1) )
  955.                  )
  956.                ) {  // sauter si lien annulΘ (ou fil vide)
  957.           if ((opt.debug>1) && (opt.log!=NULL)) {
  958.             fspc(opt.log,"debug"); fprintf(opt.log,"link #%d seems ready, skipping: %s%s.."LF,ptr,((urladr != NULL)?(urladr):(" ")),((urlfil != NULL)?(urlfil):(" ")));
  959.             test_flush;
  960.           }
  961.           ptr++;
  962.         }
  963.       }
  964.       if (liens[ptr]) {    // on a qq chose α rΘcupΘrer?
  965.  
  966.         if ( (opt.debug>1) && (opt.log!=NULL) ) {
  967.           fspc(opt.log,"debug"); fprintf(opt.log,"Wait get: %s%s"LF,urladr,urlfil);
  968.           test_flush;
  969. #if DEBUG_ROBOTS
  970.           if (strcmp(urlfil,"/robots.txt") == 0) {
  971.             printf("robots.txt detected\n");
  972.           }
  973. #endif
  974.         }    
  975.         // ------------------------------------------------------------
  976.         // DEBUT --RECUPERATION LIEN---
  977.         if (ptr==0) {              // premier lien α parcourir: lien primaire construit avant
  978.           r.adr=primary; primary=NULL;
  979.           r.statuscode=200;
  980.           r.size=strlen(r.adr);
  981.           r.soc=INVALID_SOCKET;
  982.           strcpy(r.contenttype,"text/html");
  983.         /*} else if (opt.maxsoc<=0) {   // fichiers 1 α 1 en attente (pas de backing)
  984.           // charger le fichier en mΘmoire tout bΩtement
  985.           r=xhttpget(urladr,urlfil);
  986.           //
  987.         */
  988.         } else {    // backing, multiples sockets
  989.           //
  990.           int b;
  991.           int n;
  992.           
  993. #if BDEBUG==1
  994.           printf("\nBack test..\n");
  995. #endif
  996.  
  997.           // pause/lock files
  998.           {
  999.             int do_pause=0;
  1000.  
  1001.             // user pause lockfile : create hts-paused.lock --> HTTrack will be paused
  1002.             if (fexist(fconcat(opt.path_log,"hts-stop.lock"))) {
  1003.               // remove lockfile
  1004.               remove(fconcat(opt.path_log,"hts-stop.lock"));
  1005.               if (!fexist(fconcat(opt.path_log,"hts-stop.lock"))) {
  1006.                 do_pause=1;
  1007.               }
  1008.             }
  1009.             
  1010.             // after receving N bytes, pause
  1011.             if (opt.fragment>0) {
  1012.               if ((HTS_STAT.stat_bytes-stat_fragment) > opt.fragment) {
  1013.                 do_pause=1;
  1014.               }
  1015.             }
  1016.             
  1017.             // pause?
  1018.             if (do_pause) {
  1019.               while (back_nsoc(back,back_max)>0) {                  // attendre fin des transferts
  1020.                 back_wait(back,back_max,&opt,&cache,HTS_STAT.stat_timestart);
  1021.                 Sleep(200);
  1022. #if HTS_ANALYSTE
  1023.                 {
  1024.                   back_wait(back,back_max,&opt,&cache,HTS_STAT.stat_timestart);
  1025.                   
  1026.                   // Transfer rate
  1027.                   engine_stats();
  1028.                   
  1029.                   // Refresh various stats
  1030.                   HTS_STAT.stat_nsocket=back_nsoc(back,back_max);
  1031.                   HTS_STAT.stat_errors=fspc(NULL,"error");
  1032.                   HTS_STAT.nbk=backlinks_done(liens,lien_tot,ptr);
  1033.                   HTS_STAT.nb=back_transfered(HTS_STAT.stat_bytes,back,back_max);
  1034.                   
  1035.                   b=0;
  1036.                   if (!hts_htmlcheck_loop(back,back_max,b,ptr,lien_tot,(int) (time_local()-HTS_STAT.stat_timestart),&HTS_STAT)) {
  1037.                     if (opt.errlog) {
  1038.                       fspc(opt.errlog,"info"); fprintf(opt.errlog,"Exit requested by shell or user"LF);
  1039.                       test_flush;
  1040.                     }
  1041.                     exit_xh=1;  // exit requested
  1042.                     XH_uninit;
  1043.                     return 0;
  1044.                   }
  1045.                 }
  1046. #endif
  1047.               }
  1048.               // On dΘsalloue le buffer d'enregistrement des chemins crΘΘe, au cas o∙ pendant la pause
  1049.               // l'utilisateur ferait un rm -r aprΦs avoir effectuΘ un tar
  1050.               structcheck_init(1);
  1051.               {
  1052.                 FILE* fp = fopen(fconcat(opt.path_log,"hts-paused.lock"),"wb");
  1053.                 if (fp) {
  1054.                   fspc(fp,"info");  // dater
  1055.                   fprintf(fp,"Pause"LF"HTTrack is paused after retreiving "LLintP" bytes"LF"Delete this file to continue the mirror..."LF""LF"",HTS_STAT.stat_bytes);
  1056.                   fclose(fp);
  1057.                 }
  1058.               }
  1059.               stat_fragment=HTS_STAT.stat_bytes;
  1060.               /* Info for wrappers */
  1061.               if ( (opt.debug>0) && (opt.log!=NULL) ) {
  1062.                 fspc(opt.log,"info"); fprintf(opt.log,"engine: pause: %s"LF,fconcat(opt.path_log,"hts-paused.lock"));
  1063.               }
  1064. #if HTS_ANALYSTE
  1065.               hts_htmlcheck_pause(fconcat(opt.path_log,"hts-paused.lock"));
  1066. #else
  1067.               while (fexist(fconcat(opt.path_log,"hts-paused.lock"))) {
  1068.                 //back_wait(back,back_max,&opt,&cache,HTS_STAT.stat_timestart);   inutile!! (plus de sockets actives)
  1069.                 Sleep(1000);
  1070.               }
  1071. #endif
  1072.             }
  1073.             //
  1074.           }
  1075.           // end of pause/lock files
  1076.           
  1077. #if HTS_ANALYSTE
  1078.           // changement dans les prΘfΘrences
  1079. /*
  1080.           if (_hts_setopt) {
  1081.             copy_htsopt(_hts_setopt,&opt);    // copier au besoin
  1082.             _hts_setopt=NULL;                 // effacer callback
  1083.           }
  1084. */
  1085.           if (_hts_addurl) {
  1086.             char add_adr[HTS_URLMAXSIZE*2];
  1087.             char add_fil[HTS_URLMAXSIZE*2];
  1088.             while(*_hts_addurl) {
  1089.               char add_url[HTS_URLMAXSIZE*2];
  1090.               add_adr[0]=add_fil[0]=add_url[0]='\0';
  1091.               if (strstr(*_hts_addurl,"//")==NULL)
  1092.                 strcpy(add_url,"http://");          // ajouter http://
  1093.               strcat(add_url,*_hts_addurl);
  1094.               if (ident_url_absolute(add_url,add_adr,add_fil)>=0) {
  1095.                 // ----Ajout----
  1096.                 // noter NOUVEAU lien
  1097.                 char add_sav[HTS_URLMAXSIZE*2];
  1098.                 // calculer lien et Θventuellement modifier addresse/fichier
  1099.                 if (url_savename(add_adr,add_fil,add_sav,NULL,NULL,NULL,NULL,&opt,liens,lien_tot,back,back_max,&cache,&hash,ptr,numero_passe)!=-1) { 
  1100.                   if (hash_read(&hash,add_sav,"",0)<0) {      // n'existe pas dΘja
  1101.                     // enregistrer lien (MACRO)
  1102.                     liens_record(add_adr,add_fil,add_sav,"","");
  1103.                     if (liens[lien_tot]!=NULL) {    // OK, pas d'erreur
  1104.                       liens[lien_tot]->testmode=0;          // mode test?
  1105.                       liens[lien_tot]->link_import=0;       // mode normal
  1106.                       liens[lien_tot]->depth=opt.depth;
  1107.                       liens[lien_tot]->pass2=max(0,numero_passe);
  1108.                       liens[lien_tot]->retry=opt.retry;
  1109.                       liens[lien_tot]->premier=lien_tot;
  1110.                       liens[lien_tot]->precedent=lien_tot;
  1111.                       lien_tot++;
  1112.                       //
  1113.                       if ((opt.debug>0) && (opt.log!=NULL)) {
  1114.                         fspc(opt.log,"info"); fprintf(opt.log,"Link added by user: %s%s"LF,add_adr,add_fil); test_flush;
  1115.                       }
  1116.                       //
  1117.                     } else {  // oups erreur, plus de mΘmoire!!
  1118.                       printf("PANIC! : Not enough memory [%d]\n",__LINE__);
  1119.                       if (opt.errlog) {
  1120.                         fprintf(opt.errlog,"Not enough memory, can not re-allocate %d bytes"LF,(add_tab_alloc+1)*sizeof(lien_url));
  1121.                         test_flush;
  1122.                       }
  1123.                       //if (opt.getmode & 1) { if (fp) { fclose(fp); fp=NULL; } }
  1124.                       XH_uninit;    // dΘsallocation mΘmoire & buffers
  1125.                       return 0;
  1126.                     }
  1127.                   } else {
  1128.                     if ( (opt.debug>0) && (opt.errlog!=NULL) ) {
  1129.                       fspc(opt.errlog,"warning"); fprintf(opt.errlog,"Existing link %s%s not added after user request"LF,add_adr,add_fil);
  1130.                       test_flush;
  1131.                     }
  1132.                   }
  1133.                   
  1134.                 }
  1135.               } else {
  1136.                 if (opt.errlog) {
  1137.                   fspc(opt.errlog,"error");
  1138.                   fprintf(opt.errlog,"Error during URL decoding for %s"LF,add_url);
  1139.                   test_flush;
  1140.                 }
  1141.               }
  1142.               // ----Fin Ajout----
  1143.               _hts_addurl++;                  // suivante
  1144.             }
  1145.             _hts_addurl=NULL;           // libΘrer _hts_addurl
  1146.           }
  1147.           // si une pause a ΘtΘ demandΘe
  1148.           if (_hts_setpause) {
  1149.             // index du lien actuel
  1150.             int b=back_index(back,back_max,urladr,urlfil,savename);
  1151.             if (b<0) b=0;    // forcer pour les stats
  1152.             while(_hts_setpause) {    // on fait la pause..
  1153.               back_wait(back,back_max,&opt,&cache,HTS_STAT.stat_timestart);
  1154.  
  1155.               // Transfer rate
  1156.               engine_stats();
  1157.  
  1158.               // Refresh various stats
  1159.               HTS_STAT.stat_nsocket=back_nsoc(back,back_max);
  1160.               HTS_STAT.stat_errors=fspc(NULL,"error");
  1161.               HTS_STAT.nbk=backlinks_done(liens,lien_tot,ptr);
  1162.               HTS_STAT.nb=back_transfered(HTS_STAT.stat_bytes,back,back_max);
  1163.  
  1164.               if (!hts_htmlcheck_loop(back,back_max,b,ptr,lien_tot,(int) (time_local()-HTS_STAT.stat_timestart),&HTS_STAT)) {
  1165.                 if (opt.errlog) {
  1166.                   fspc(opt.errlog,"info"); fprintf(opt.errlog,"Exit requested by shell or user"LF);
  1167.                   test_flush;
  1168.                 }
  1169.                 exit_xh=1;  // exit requested
  1170.                 XH_uninit;
  1171.                 return 0;
  1172.               }
  1173.               if (back_nsoc(back,back_max)==0)
  1174.                 Sleep(250);  // tite pause
  1175.             }
  1176.           }
  1177. #endif
  1178.           
  1179.           // si le fichier n'est pas en backing, le mettre..
  1180.           if (!back_exist(back,back_max,urladr,urlfil,savename)) {
  1181. #if BDEBUG==1
  1182.             printf("crash backing: %s%s\n",liens[ptr]->adr,liens[ptr]->fil);
  1183. #endif
  1184.             if (back_add(back,back_max,&opt,&cache,urladr,urlfil,savename,liens[liens[ptr]->precedent]->adr,liens[liens[ptr]->precedent]->fil,liens[ptr]->testmode,&liens[ptr]->pass2)==-1) {
  1185.               printf("PANIC! : Crash adding error, unexpected error found.. [%d]\n",__LINE__);
  1186. #if BDEBUG==1
  1187.               printf("error while crash adding\n");
  1188. #endif
  1189.               if (opt.errlog) {
  1190.                 fspc(opt.errlog,"error"); fprintf(opt.errlog,"Unexpected backing error for %s%s"LF,urladr,urlfil);
  1191.                 test_flush;
  1192.               } 
  1193.               
  1194.             }
  1195.           }
  1196.           
  1197. #if BDEBUG==1
  1198.           printf("test number of socks\n");
  1199. #endif
  1200.           
  1201.           // ajouter autant de socket qu'on peut ajouter
  1202.           n=opt.maxsoc-back_nsoc(back,back_max);
  1203. #if BDEBUG==1
  1204.           printf("%d sockets available for backing\n",n);
  1205. #endif
  1206.  
  1207. #if HTS_ANALYSTE
  1208.           if ((n>0) && (!_hts_setpause)) {   // si sockets libre et pas en pause, ajouter
  1209. #else
  1210.           if (n>0) {                         // si sockets libre
  1211. #endif
  1212.             // remplir autant que l'on peut le cache (backing)
  1213.             back_fillmax(back,back_max,&opt,&cache,liens,ptr,numero_passe,lien_tot);
  1214.           }
  1215.           
  1216.           // index du lien actuel
  1217. /*
  1218.           b=back_index(back,back_max,urladr,urlfil,savename);
  1219.           
  1220.           if (b>=0) 
  1221. */
  1222.           {
  1223.             // ------------------------------------------------------------
  1224.             // attendre que le fichier actuel soit prΩt - BOUCLE D'ATTENTE
  1225.             do {
  1226.  
  1227.               // index du lien actuel
  1228.               b=back_index(back,back_max,urladr,urlfil,savename);
  1229. #if BDEBUG==1
  1230.               printf("back index %d, waiting\n",b);
  1231. #endif
  1232.               // Continue to the loop if link still present
  1233.               if (b<0)
  1234.                 continue;
  1235.               
  1236.               // Receive data
  1237.               if (back[b].status>0)
  1238.                 back_wait(back,back_max,&opt,&cache,HTS_STAT.stat_timestart);
  1239.               
  1240.               // Continue to the loop if link still present
  1241.               b=back_index(back,back_max,urladr,urlfil,savename);
  1242.               if (b<0)
  1243.                 continue;
  1244.               
  1245.               // And fill the backing stack
  1246.               if (back[b].status>0)
  1247.                 back_fillmax(back,back_max,&opt,&cache,liens,ptr,numero_passe,lien_tot);
  1248.               
  1249.               // Continue to the loop if link still present
  1250.               b=back_index(back,back_max,urladr,urlfil,savename);
  1251.               if (b<0)
  1252.                 continue;
  1253.  
  1254.               // autres occupations de HTTrack: statistiques, boucle d'attente, etc.
  1255.               if ((opt.makestat) || (opt.maketrack)) {
  1256.                 TStamp l=time_local();
  1257.                 if ((int) (l-makestat_time) >= 60) {   
  1258.                   if (makestat_fp != NULL) {
  1259.                     fspc(makestat_fp,"info");
  1260.                     fprintf(makestat_fp,"Rate= %d (/"LLintP") \11NewLinks= %d (/%d)"LF,(int) ((HTS_STAT.HTS_TOTAL_RECV-makestat_total)/(l-makestat_time)), HTS_STAT.HTS_TOTAL_RECV,(int) lien_tot-makestat_lnk,(int) lien_tot);
  1261.                     fflush(makestat_fp);
  1262.                     makestat_total=HTS_STAT.HTS_TOTAL_RECV;
  1263.                     makestat_lnk=lien_tot;
  1264.                   }
  1265.                   if (maketrack_fp!=NULL) {
  1266.                     int i;
  1267.                     fspc(maketrack_fp,"info"); fprintf(maketrack_fp,LF);
  1268.                     for(i=0;i<back_max;i++) {
  1269.                       back_info(back,i,3,maketrack_fp);
  1270.                     }
  1271.                     fprintf(maketrack_fp,LF);
  1272.                     
  1273.                   }
  1274.                   makestat_time=l;
  1275.                 }
  1276.               }
  1277. #if HTS_ANALYSTE
  1278.               {
  1279.                 int i;
  1280.                 {
  1281.                   char* s=hts_cancel_file("");
  1282.                   if (strnotempty(s)) {    // fichier α canceller
  1283.                     for(i=0;i<back_max;i++) {
  1284.                       if ((back[i].status>0)) {
  1285.                         if (strcmp(back[i].url_sav,s)==0) {  // ok trouvΘ
  1286.                           if (back[i].status != 1000) {
  1287. #if HTS_DEBUG_CLOSESOCK
  1288.                             DEBUG_W("user cancel: deletehttp\n");
  1289. #endif
  1290.                             if (back[i].r.soc!=INVALID_SOCKET) deletehttp(&back[i].r);
  1291.                             back[i].r.soc=INVALID_SOCKET;
  1292.                             back[i].r.statuscode=-1;
  1293.                             strcpy(back[i].r.msg,"Cancelled by User");
  1294.                             back[i].status=0;  // terminΘ
  1295.                           } else    // cancel ftp.. flag α 1
  1296.                             back[i].stop_ftp = 1;
  1297.                         }
  1298.                       }
  1299.                     }
  1300.                     s[0]='\0';
  1301.                   }
  1302.                 }
  1303.                 
  1304.                 // Transfer rate
  1305.                 engine_stats();
  1306.                 
  1307.                 // Refresh various stats
  1308.                 HTS_STAT.stat_nsocket=back_nsoc(back,back_max);
  1309.                 HTS_STAT.stat_errors=fspc(NULL,"error");
  1310.                 HTS_STAT.nbk=backlinks_done(liens,lien_tot,ptr);
  1311.                 HTS_STAT.nb=back_transfered(HTS_STAT.stat_bytes,back,back_max);
  1312.                 
  1313.                 if (!hts_htmlcheck_loop(back,back_max,b,ptr,lien_tot,(int) (time_local()-HTS_STAT.stat_timestart),&HTS_STAT)) {
  1314.                   if (opt.errlog) {
  1315.                     fspc(opt.errlog,"info"); fprintf(opt.errlog,"Exit requested by shell or user"LF);
  1316.                     test_flush;
  1317.                   } 
  1318.                   exit_xh=1;  // exit requested
  1319.                   XH_uninit;
  1320.                   return 0;
  1321.                 }
  1322.               }
  1323.               
  1324. #endif
  1325. #if HTS_POLL
  1326.               if ((opt.shell) || (opt.keyboard) || (opt.verbosedisplay) || (!opt.quiet)) {
  1327.                 TStamp tl;
  1328.                 info_shell=1;
  1329.  
  1330.                 /* Toggle with ENTER */
  1331.                 if (!opt.quiet) {
  1332.                   if (check_stdin()) {
  1333.                     char com[256];
  1334.                     linput(stdin,com,200);
  1335.                     if (opt.verbosedisplay==2)
  1336.                       opt.verbosedisplay=1;
  1337.                     else
  1338.                       opt.verbosedisplay=2;
  1339.                     /* Info for wrappers */
  1340.                     if ( (opt.debug>0) && (opt.log!=NULL) ) {
  1341.                       fspc(opt.log,"info"); fprintf(opt.log,"engine: change-options"LF);
  1342.                     }
  1343. #if HTS_ANALYSTE
  1344.                     hts_htmlcheck_chopt(&opt);
  1345. #endif
  1346.                   }
  1347.                 }
  1348.  
  1349.                 /*
  1350.                 ..useless..
  1351.                 while (check_stdin()) {  // donnΘes disponibles
  1352.                   char com[256];
  1353.                   com[0]='\0';
  1354.                   
  1355.                   if (!rcvd) rcvd=1;
  1356.                   linput(stdin,com,256);
  1357.  
  1358.                   if (strnotempty(com)) {
  1359.                     if (strlen(com)<=2) {
  1360.                       switch(*com) {
  1361.                       case '?': {    // Status?
  1362.                         if (back[b].status>0) printf("WAIT\n"); 
  1363.                         else printf("READY\n");
  1364.                                 }
  1365.                         break;
  1366.                       case 'f': {    // Fichier en attente?
  1367.                         if (back[b].status>0) printf("WAIT %s\n",back[b].url_fil); 
  1368.                         else printf("READY %s\n",back[b].url_fil);
  1369.                                 }
  1370.                         break;
  1371.                       case 'A': case 'F': {    // filters
  1372.                         int i;
  1373.                         for(i=0;i<filptr;i++) {
  1374.                           printf("%s ",filters[i]);
  1375.                         }
  1376.                         printf("\n");
  1377.                                 }
  1378.                         break;
  1379.                       case '#': {    // Afficher statistique sur le nombre de liens, etc
  1380.                         switch(*(com+1)) {
  1381.                         case 'l': printf("%d\n",lien_tot); break;  // nombre de liens enregistrΘs
  1382.                         case 's': printf("%d\n",back_nsoc(back,back_max)); break;  // nombre de sockets
  1383.                         case 'r': printf("%d\n",(int) (HTS_STAT.HTS_TOTAL_RECV/(time_local()-HTS_STAT.stat_timestart))); break;  // taux de transfert
  1384.                         }
  1385.                                 }
  1386.                         break;
  1387.                       case 'K': if (*(com+1)=='!') {  // Kill
  1388.                         XH_uninit;
  1389.                         return -1;
  1390.                                 }
  1391.                         break;
  1392.                       case 'X': if (*(com+1)=='!') {  // exit
  1393.                         exit_xh=1;
  1394.                                 }
  1395.                         break;
  1396.                       case 'I': if (*(com+1)=='+') info_shell=1; else info_shell=0;
  1397.                         break;
  1398.                       }
  1399.                       io_flush;
  1400.                     } else if (*com=='@') {
  1401.                       printf("%s\n",com+1);
  1402.                       io_flush;
  1403.                     }
  1404.                   } 
  1405.                   
  1406.                 }  // while
  1407.                 */
  1408.                 tl=time_local();
  1409.                 
  1410.                 // gΘnΘrer un message d'infos sur l'Θtat actuel
  1411.                 if (opt.shell) {    // si shell
  1412.                   if ((tl-last_info_shell)>0) {    // toute les 1 sec
  1413.                     FILE* fp=stdout;
  1414.                     int a=0;
  1415.                     last_info_shell=tl;
  1416.                     if (fexist(fconcat(opt.path_log,"hts-autopsy"))) {  // dΘbuggage: teste si le robot est vivant
  1417.                       // (oui je sais un robot vivant.. mais bon.. il a le droit de vivre lui aussi)
  1418.                       // (libΘrons les robots esclaves de l'internet!)
  1419.                       remove(fconcat(opt.path_log,"hts-autopsy"));
  1420.                       fp=fopen(fconcat(opt.path_log,"hts-isalive"),"wb");
  1421.                       a=1;
  1422.                     }
  1423.                     if ((info_shell) || a) {
  1424.                       int i,j;
  1425.                       
  1426.                       fprintf(fp,"TIME %d"LF,(int) (tl-HTS_STAT.stat_timestart));
  1427.                       fprintf(fp,"TOTAL %d"LF,(int) HTS_STAT.stat_bytes);
  1428.                       fprintf(fp,"RATE %d"LF,(int) (HTS_STAT.HTS_TOTAL_RECV/(tl-HTS_STAT.stat_timestart)));
  1429.                       fprintf(fp,"SOCKET %d"LF,back_nsoc(back,back_max));
  1430.                       fprintf(fp,"LINK %d"LF,lien_tot);
  1431.                       {
  1432.                         LLint mem=0;
  1433.                         for(i=0;i<back_max;i++)
  1434.                           if (back[i].r.adr!=NULL)
  1435.                             mem+=back[i].r.size;
  1436.                           fprintf(fp,"INMEM "LLintP""LF,mem);
  1437.                       }
  1438.                       for(j=0;j<2;j++) {  // passes pour ready et wait
  1439.                         for(i=0;i<back_max;i++) {
  1440.                           back_info(back,i,j+1,stdout);    // maketrack_fp a la place de stdout ?? // **
  1441.                         }
  1442.                       }
  1443.                       fprintf(fp,LF);
  1444.                       if (a)
  1445.                         fclose(fp);
  1446.                       io_flush;
  1447.                     }
  1448.                   }
  1449.                 }  // si shell
  1450.                 
  1451.               }  // si shell ou keyboard (option)
  1452.               //
  1453. #endif
  1454.             } while((b>=0) && (back[max(b,0)].status>0));
  1455.  
  1456.  
  1457.             // If link not found on the stack, it's because it has already been downloaded
  1458.             // in background
  1459.             // Then, skip it and go to the next one
  1460.             if (b<0) {
  1461.               if ((opt.debug>1) && (opt.log!=NULL)) {
  1462.                 fspc(opt.log,"debug"); fprintf(opt.log,"link #%d is ready, no more on the stack, skipping: %s%s.."LF,ptr,urladr,urlfil);
  1463.                 test_flush;
  1464.               }
  1465.  
  1466.               // prochain lien
  1467.               // ptr++;
  1468.  
  1469.               // Jump to 'continue'
  1470.               // This is one of the very very rare cases where goto
  1471.               // is acceptable
  1472.               // A supplemental flag and if( ) { } would be really messy
  1473.               goto jump_if_done;
  1474.             }
  1475.             
  1476.  
  1477. #if HTS_ANALYSTE==2
  1478. #else
  1479.             //if (!opt.quiet) {  // petite animation
  1480.             if (!opt.verbosedisplay) {
  1481.               if (!opt.quiet) {
  1482.                 static int roll=0;
  1483.                 roll=(roll+1)%4;
  1484.                 printf("%c\x0d",("/-\\|")[roll]);
  1485.                 fflush(stdout);
  1486.               }
  1487.             } else if (opt.verbosedisplay==1) {
  1488.               if (back[b].r.statuscode==200)
  1489.                 printf("%d/%d: %s%s ("LLintP" bytes) - OK\33[K\r",ptr,lien_tot,back[b].url_adr,back[b].url_fil,back[b].r.size);
  1490.               else
  1491.                 printf("%d/%d: %s%s ("LLintP" bytes) - %d\33[K\r",ptr,lien_tot,back[b].url_adr,back[b].url_fil,back[b].r.size,back[b].r.statuscode);
  1492.               fflush(stdout);
  1493.             }
  1494.             //}
  1495. #endif
  1496.             // ------------------------------------------------------------
  1497.             // VΘrificateur d'intΘgritΘ
  1498. #if DEBUG_CHECKINT
  1499.             _CHECKINT(&back[b],"Retour de back_wait, aprΦs le while")
  1500.             {
  1501.               int i;
  1502.               for(i=0;i<back_max;i++) {
  1503.                 char si[256];
  1504.                 sprintf(si,"Test global aprΦs back_wait, index %d",i);
  1505.                 _CHECKINT(&back[i],si)
  1506.               }
  1507.             }
  1508. #endif
  1509.             
  1510.             // copier structure rΘponse htsblk
  1511.             bcopy((char*) &(back[b].r), (char*) &r, sizeof(htsblk));
  1512.             r.location=loc;    // ne PAS copier location!! adresse, pas de buffer
  1513.             if (back[b].r.location) 
  1514.               strcpy(r.location,back[b].r.location);
  1515.             back[b].r.adr=NULL;    // ne pas faire de desalloc ensuite
  1516.  
  1517.             // libΘrer emplacement backing
  1518.             back_delete(back,b);
  1519.             
  1520.             // progression
  1521.             if (opt.aff_progress) {
  1522.               TStamp tl=time_local();
  1523.               if ((tl-HTS_STAT.stat_timestart)>0) {
  1524.                 char s[32];
  1525.                 int i=0;
  1526.                 lastime=tl;
  1527.                 _CLRSCR; _GOTOXY("1","1");
  1528.                 printf("Rate=%d B/sec\n",(int) (HTS_STAT.HTS_TOTAL_RECV/(tl-HTS_STAT.stat_timestart)));
  1529.                 while(i<minimum(back_max,99)) {  // **
  1530.                   if (back[i].status>=0) {  // loading..
  1531.                     s[0]='\0';
  1532.                     if (strlen(back[i].url_fil)>16)
  1533.                       strcat(s,back[i].url_fil+strlen(back[i].url_fil)-16);       
  1534.                     else
  1535.                       strncat(s,back[i].url_fil,16);
  1536.                     printf("%s : ",s);
  1537.                     
  1538.                     printf("[");
  1539.                     if (back[i].r.totalsize>0) {
  1540.                       int p;
  1541.                       int j;
  1542.                       p=(int)((back[i].r.size*10)/back[i].r.totalsize);
  1543.                       p=minimum(10,p);
  1544.                       for(j=0;j<p;j++) printf("*");
  1545.                       for(j=0;j<(10-p);j++) printf("-");
  1546.                     } else { 
  1547.                       printf(LLintP,back[i].r.size);                      
  1548.                     }
  1549.                     printf("]");
  1550.                     
  1551.                     //} else if (back[i].status==0) {
  1552.                     //  strcpy(s,"ENDED");
  1553.                   } 
  1554.                   printf("\n");
  1555.                   i++;
  1556.                 }
  1557.                 io_flush;
  1558.               }
  1559.             }
  1560.             
  1561.             // dΘbug graphique
  1562. #if BDEBUG==2
  1563.             {
  1564.               char s[12];
  1565.               int i=0;
  1566.               _GOTOXY(1,1);
  1567.               printf("Rate=%d B/sec\n",(int) (HTS_STAT.HTS_TOTAL_RECV/(time_local()-HTS_STAT.stat_timestart)));
  1568.               while(i<minimum(back_max,160)) {
  1569.                 if (back[i].status>0) {
  1570.                   sprintf(s,"%d",back[i].r.size);
  1571.                 } else if (back[i].status==0) {
  1572.                   strcpy(s,"ENDED");
  1573.                 } else 
  1574.                   strcpy(s,"   -   ");
  1575.                 while(strlen(s)<8) strcat(s," ");
  1576.                 printf("%s",s); io_flush;
  1577.                 i++;
  1578.               }
  1579.             }
  1580. #endif
  1581.             
  1582.             
  1583. #if BDEBUG==1
  1584.             printf("statuscode=%d with %s / msg=%s\n",r.statuscode,r.contenttype,r.msg);
  1585. #endif
  1586.             
  1587.           }
  1588.           /*else {
  1589. #if BDEBUG==1
  1590.             printf("back index error\n");
  1591. #endif
  1592.           }
  1593.           */
  1594.           
  1595.         }
  1596.         // FIN --RECUPERATION LIEN--- 
  1597.         // ------------------------------------------------------------
  1598.  
  1599.  
  1600.  
  1601.       } else {    // lien vide..
  1602.         if (opt.errlog) {
  1603.           fspc(opt.errlog,"warning"); fprintf(opt.errlog,"Warning, link #%d empty"LF,ptr); test_flush;
  1604.           error=1;
  1605.         }         
  1606.       }  // test si url existe (non vide!)
  1607.       
  1608.  
  1609.  
  1610.       // ---tester taille a posteriori---
  1611.       // tester r.adr
  1612.       if (!error) {
  1613.         // erreur, pas de fichier chargΘ:
  1614.         if ((!r.adr) && (r.is_write==0) 
  1615.           && (r.statuscode!=301) 
  1616.           && (r.statuscode!=302) 
  1617.           && (r.statuscode!=303) 
  1618.           && (r.statuscode!=307) 
  1619.           && (r.statuscode!=412)
  1620.           && (r.statuscode!=416)
  1621.          ) { 
  1622.           // error=1;
  1623.           
  1624.           // peut Ωtre que le fichier Θtait trop gros?
  1625.           if ((istoobig(r.totalsize,opt.maxfile_html,opt.maxfile_nonhtml,r.contenttype))
  1626.            || (istoobig(r.totalsize,opt.maxfile_html,opt.maxfile_nonhtml,r.contenttype))) {
  1627.             error=0;
  1628.             if (opt.errlog) {
  1629.               fspc(opt.errlog,"warning"); fprintf(opt.errlog,"Big file cancelled according to user's preferences: %s%s"LF,urladr,urlfil);
  1630.               test_flush;
  1631.             }
  1632.           }
  1633.           // // // error=1;    // ne pas traiter la suite -- euhh si finalement..
  1634.         }
  1635.       }
  1636.       // ---fin tester taille a posteriori---    
  1637.  
  1638.  
  1639.       // -------------------- 
  1640.       // BOGUS MIME TYPE HACK
  1641.       // Check if we have a bogus MIME type
  1642.       // example: 
  1643.       // Content-type="text/html"
  1644.       // and 
  1645.       // Content-disposition="foo.jpg"
  1646.       // --------------------
  1647.       if (!error) {
  1648.         if (r.statuscode == 200) {    // OK (ou 304 en backing)
  1649.           if (r.adr) {    // Written file
  1650.             if ( (is_hypertext_mime(r.contenttype))   /* Is HTML or Js, .. */
  1651.               || (may_be_hypertext_mime(r.contenttype) && (r.adr) )  /* Is real media, .. */
  1652.               ) {
  1653.               if (strnotempty(r.cdispo)) {      // Content-disposition set!
  1654.                 if (ishtml(savename) == 0) {    // Non HTML!!
  1655.                   // patch it!
  1656.                   strcpy(r.contenttype,"application/octet-stream");
  1657.                 }
  1658.               }
  1659.             }
  1660.           }
  1661.         }
  1662.       }
  1663.       
  1664.  
  1665.       // -------------------- 
  1666.       // REAL MEDIA HACK
  1667.       // Check if we have to load locally the file
  1668.       // --------------------
  1669.       if (!error) {
  1670.         if (r.statuscode == 200) {    // OK (ou 304 en backing)
  1671.           if (r.adr==NULL) {    // Written file
  1672.             if (may_be_hypertext_mime(r.contenttype)) {   // to parse!
  1673.               LLint sz;
  1674.               sz=fsize(savename);
  1675.               if (sz>0) {   // ok, exists!
  1676.                 if (sz < 512) {   // ok, small file --> to parse!
  1677.                   FILE* fp=fopen(savename,"rb");
  1678.                   if (fp) {
  1679.                     r.adr=malloct((int)sz + 2);
  1680.                     if (r.adr) {
  1681.                       fread(r.adr,(int)sz,1,fp);
  1682.                       r.size=sz;
  1683.                       // remove (temporary) file!
  1684.                       remove(savename);
  1685.                     }
  1686.                     fclose(fp);
  1687.                   }
  1688.                 }
  1689.               }
  1690.             }
  1691.           }
  1692.         }
  1693.       }
  1694.       // EN OF REAL MEDIA HACK
  1695.       
  1696.  
  1697.       // ---stockage en cache---
  1698.       // stocker dans le cache?
  1699.       /*
  1700.       if (!error) {
  1701.         if (ptr>0) {
  1702.           if (liens[ptr]) {
  1703.             cache_mayadd(&opt,&cache,&r,urladr,urlfil,savename);
  1704.           } else
  1705.             error=1;
  1706.         }
  1707.       }
  1708.       */
  1709.       // ---fin stockage en cache---
  1710.       
  1711.  
  1712.  
  1713.       // DEBUT rattrapage des 301,302,307..
  1714.       // ------------------------------------------------------------
  1715.       if (!error) {
  1716.         ////////{
  1717.         // on a chargΘ un fichier en plus
  1718.         // if (!error) stat_loaded+=r.size;
  1719.         
  1720.         // ------------------------------------------------------------
  1721.         // Rattrapage des 301,302,307 (moved) et 412,416 - les 304 le sont dans le backing 
  1722.         // ------------------------------------------------------------
  1723.         if ( (r.statuscode==301) 
  1724.           || (r.statuscode==302)
  1725.           || (r.statuscode==303)
  1726.           || (r.statuscode==307)
  1727.           ) {          
  1728.           //if (r.adr!=NULL) {   // adr==null si fichier direct. [catch: davename normalement si cgi]
  1729.           //int i=0;
  1730.           char *rn=NULL;
  1731.           // char* p;
  1732.           
  1733.           if ( (opt.debug>0) && (opt.errlog!=NULL) ) {
  1734.             //if (opt.errlog) {
  1735.             fspc(opt.errlog,"warning"); fprintf(opt.errlog,"%s for %s%s"LF,r.msg,urladr,urlfil);
  1736.             test_flush;
  1737.           }
  1738.           
  1739.           
  1740.           {
  1741.             char mov_url[HTS_URLMAXSIZE*2],mov_adr[HTS_URLMAXSIZE*2],mov_fil[HTS_URLMAXSIZE*2];
  1742.             int get_it=0;         // ne pas prendre le fichier α la mΩme adresse par dΘfaut
  1743.             int reponse=0;
  1744.             mov_url[0]='\0'; mov_adr[0]='\0'; mov_fil[0]='\0';
  1745.             //
  1746.             
  1747.             strcpy(mov_url,r.location);
  1748.             
  1749.             // url qque -> adresse+fichier
  1750.             if ((reponse=ident_url_relatif(mov_url,urladr,urlfil,mov_adr,mov_fil))>=0) {                        
  1751.               int set_prio_to=0;    // pas de priotitΘ fixΘd par wizard
  1752.               
  1753.               //if (ident_url_absolute(mov_url,mov_adr,mov_fil)!=-1) {    // ok URL reconnue
  1754.               // c'est (en gros) la mΩme URL..
  1755.               // si c'est un problΦme de casse dans le host c'est que le serveur est buggΘ
  1756.               // ("RFC says.." : host name IS case insensitive)
  1757.               if ((strfield2(mov_adr,urladr)!=0) && (strfield2(mov_fil,urlfil)!=0)) {  // identique α casse prΦs
  1758.                 // on tourne en rond
  1759.                 if (strcmp(mov_fil,urlfil)==0) {
  1760.                   error=1;
  1761.                   get_it=-1;        // ne rien faire
  1762.                   if (opt.errlog) {
  1763.                     fspc(opt.errlog,"warning"); fprintf(opt.errlog,"Can not bear crazy server (%s) for %s%s"LF,r.msg,urladr,urlfil);
  1764.                     test_flush;
  1765.                   }
  1766.                 } else {    // mauvaise casse, effacer entrΘe dans la pile et rejouer une fois
  1767.                   get_it=1;
  1768.                 }
  1769.               } else {        // adresse diffΘrente
  1770.                 if (ishtml(mov_url)==0) {   // pas mΩme adresse MAIS c'est un fichier non html (pas de page moved possible)
  1771.                   // -> on prend α cette adresse, le lien sera enregistrΘ avec lien_record() (hash)
  1772.                   if ((opt.debug>1) && (opt.log!=NULL)) {
  1773.                     fspc(opt.log,"debug"); fprintf(opt.log,"wizard link test for moved file at %s%s.."LF,mov_adr,mov_fil);
  1774.                     test_flush;
  1775.                   }
  1776.                   // acceptΘ?
  1777.                   if (hts_acceptlink(&opt,ptr,lien_tot,liens,
  1778.                     mov_adr,mov_fil,
  1779.                     filters,&filptr,filter_max,
  1780.                     &robots,
  1781.                     &set_prio_to,
  1782.                     NULL) != 1) {                /* nouvelle adresse non refusΘe ? */
  1783.                     get_it=1;
  1784.                     if ((opt.debug>1) && (opt.log!=NULL)) {
  1785.                       fspc(opt.log,"debug"); fprintf(opt.log,"moved link accepted: %s%s"LF,mov_adr,mov_fil);
  1786.                       test_flush;
  1787.                     }
  1788.                   }
  1789.                 } /* sinon traitΘ normalement */
  1790.               }
  1791.               
  1792.               //if ((strfield2(mov_adr,urladr)!=0) && (strfield2(mov_fil,urlfil)!=0)) {  // identique α casse prΦs
  1793.               if (get_it==1) {
  1794.                 // court-circuiter le reste du traitement
  1795.                 // et reculer pour mieux sauter
  1796.                 if (opt.errlog) {
  1797.                   fspc(opt.errlog,"warning"); fprintf(opt.errlog,"Warning moved treated for %s%s (real one is %s%s)"LF,urladr,urlfil,mov_adr,mov_fil);
  1798.                   test_flush;
  1799.                 }          
  1800.                 // canceller lien actuel
  1801.                 error=1;
  1802.                 strcpy(liens[ptr]->adr,"!");  // caractΦre bidon (invalide hash)
  1803. #if HTS_HASH
  1804. #else
  1805.                 liens[ptr]->sav_len=-1;       // taille invalide
  1806. #endif
  1807.                 // noter NOUVEAU lien
  1808.                 {
  1809.                   char mov_sav[HTS_URLMAXSIZE*2];
  1810.                   // calculer lien et Θventuellement modifier addresse/fichier
  1811.                   if (url_savename(mov_adr,mov_fil,mov_sav,NULL,NULL,liens[liens[ptr]->precedent]->adr,liens[liens[ptr]->precedent]->fil,&opt,liens,lien_tot,back,back_max,&cache,&hash,ptr,numero_passe)!=-1) { 
  1812.                     if (hash_read(&hash,mov_sav,"",0)<0) {      // n'existe pas dΘja
  1813.                       // enregistrer lien (MACRO) avec SAV IDENTIQUE
  1814.                       liens_record(mov_adr,mov_fil,liens[ptr]->sav,"","");
  1815.                       //liens_record(mov_adr,mov_fil,mov_sav,"","");
  1816.                       if (liens[lien_tot]!=NULL) {    // OK, pas d'erreur
  1817.                         // mode test?
  1818.                         liens[lien_tot]->testmode=liens[ptr]->testmode;
  1819.                         liens[lien_tot]->link_import=0;       // mode normal
  1820.                         if (!set_prio_to)
  1821.                           liens[lien_tot]->depth=liens[ptr]->depth;
  1822.                         else
  1823.                           liens[lien_tot]->depth=max(0,min(set_prio_to-1,liens[ptr]->depth));       // PRIORITE NULLE (catch page)
  1824.                         liens[lien_tot]->pass2=max(liens[ptr]->pass2,numero_passe);
  1825.                         liens[lien_tot]->retry=liens[ptr]->retry;
  1826.                         liens[lien_tot]->premier=liens[ptr]->premier;
  1827.                         liens[lien_tot]->precedent=liens[ptr]->precedent;
  1828.                         lien_tot++;
  1829.                       } else {  // oups erreur, plus de mΘmoire!!
  1830.                         printf("PANIC! : Not enough memory [%d]\n",__LINE__);
  1831.                         if (opt.errlog) {
  1832.                           fprintf(opt.errlog,"Not enough memory, can not re-allocate %d bytes"LF,(add_tab_alloc+1)*sizeof(lien_url));
  1833.                           test_flush;
  1834.                         }
  1835.                         //if (opt.getmode & 1) { if (fp) { fclose(fp); fp=NULL; } }
  1836.                         XH_uninit;    // dΘsallocation mΘmoire & buffers
  1837.                         return 0;
  1838.                       }
  1839.                     } else {
  1840.                       if ( (opt.debug>0) && (opt.errlog!=NULL) ) {
  1841.                         fspc(opt.errlog,"warning"); fprintf(opt.errlog,"moving %s to an existing file %s"LF,liens[ptr]->fil,urlfil);
  1842.                         test_flush;
  1843.                       }
  1844.                     }
  1845.                     
  1846.                   }
  1847.                 }
  1848.                 
  1849.                 //printf("-> %s %s %s\n",liens[lien_tot-1]->adr,liens[lien_tot-1]->fil,liens[lien_tot-1]->sav);
  1850.                 
  1851.                 // note mΘtaphysique: il se peut qu'il y ait un index.html et un INDEX.HTML
  1852.                 // sous DOS ca marche pas trΦs bien... mais comme je suis gΘnial url_savename()
  1853.                 // est α mΩme de rΘgler ce problΦme
  1854.               }
  1855.             } // ident_url_xx
  1856.             
  1857.             if (get_it==0) {    // adresse vraiment diffΘrente et potentiellement en html (pas de possibilitΘ de bouger la page tel quel α cause des <img src..> et cie)
  1858.               rn=(char*) calloct(8192,1);
  1859.               if (rn!=NULL) {
  1860.                 if (opt.errlog) {
  1861.                   fspc(opt.errlog,"warning"); fprintf(opt.errlog,"File has moved from %s%s to %s"LF,urladr,urlfil,mov_url);
  1862.                   test_flush;
  1863.                 }
  1864.                 escape_uri(mov_url);
  1865.                 // On prΘpare une page qui sautera immΘdiatement sur la bonne URL
  1866.                 // Le scanner re-changera, ensuite, cette URL, pour la mirrorer!
  1867.                 strcpy(rn,"<HTML>"CRLF);
  1868.                 strcat(rn,"<!-- Created by HTTrack Website Copier/"HTTRACK_VERSION" "HTTRACK_AFF_AUTHORS" -->"CRLF);
  1869.                 strcat(rn,"<HEAD>"CRLF"<TITLE>Page has moved</TITLE>"CRLF"</HEAD>"CRLF"<BODY>"CRLF);
  1870.                 strcat(rn,"<META HTTP-EQUIV=\"Refresh\" CONTENT=\"0; URL=");
  1871.                 strcat(rn,mov_url);    // URL
  1872.                 strcat(rn,"\">"CRLF);
  1873.                 strcat(rn,"<A HREF=\"");
  1874.                 strcat(rn,mov_url);
  1875.                 strcat(rn,"\">");
  1876.                 strcat(rn,"<B>Click here...</B></A>"CRLF);
  1877.                 strcat(rn,"</BODY>"CRLF);
  1878.                 strcat(rn,"<!-- Created by HTTrack Website Copier/"HTTRACK_VERSION" "HTTRACK_AFF_AUTHORS" -->"CRLF);
  1879.                 strcat(rn,"</HTML>"CRLF);
  1880.                 
  1881.                 // changer la page
  1882.                 if (r.adr) { freet(r.adr); r.adr=NULL; }
  1883.                 r.adr=rn;
  1884.                 r.size=strlen(r.adr);
  1885.                 strcpy(r.contenttype,"text/html");
  1886.               }
  1887.             }  // get_it==0
  1888.             
  1889.           }     // bloc
  1890.         // erreur HTTP (ex: 404, not found)
  1891.         } else if (   (r.statuscode==412)
  1892.           || (r.statuscode==416)
  1893.           ) {    // Precondition Failed, c'est α dire pour nous redemander TOUT le fichier
  1894.           if (fexist(liens[ptr]->sav)) {
  1895.             remove(liens[ptr]->sav);    // Eliminer
  1896.             if (!fexist(liens[ptr]->sav)) {  // Bien ΘliminΘ? (sinon on boucle..)
  1897. #if HDEBUG
  1898.               printf("Partial content NOT up-to-date, reget all file for %s\n",liens[ptr]->sav);
  1899. #endif
  1900.               if ( (opt.debug>1) && (opt.errlog!=NULL) ) {
  1901.                 //if (opt.errlog) {
  1902.                 fspc(opt.errlog,"debug"); fprintf(opt.errlog,"Partial file reget (%s) for %s%s"LF,r.msg,urladr,urlfil);
  1903.                 test_flush;
  1904.               }
  1905.               // enregistrer le MEME lien (MACRO)
  1906.               liens_record(liens[ptr]->adr,liens[ptr]->fil,liens[ptr]->sav,"","");
  1907.               if (liens[lien_tot]!=NULL) {    // OK, pas d'erreur
  1908.                 liens[lien_tot]->testmode=liens[ptr]->testmode;          // mode test?
  1909.                 liens[lien_tot]->link_import=0;       // pas mode import
  1910.                 liens[lien_tot]->depth=liens[ptr]->depth;
  1911.                 liens[lien_tot]->pass2=max(liens[ptr]->pass2,numero_passe);
  1912.                 liens[lien_tot]->retry=liens[ptr]->retry;
  1913.                 liens[lien_tot]->premier=liens[ptr]->premier;
  1914.                 liens[lien_tot]->precedent=ptr;
  1915.                 lien_tot++;
  1916.                 //
  1917.                 // canceller lien actuel
  1918.                 error=1;
  1919.                 strcpy(liens[ptr]->adr,"!");  // caractΦre bidon (invalide hash)
  1920. #if HTS_HASH
  1921. #else
  1922.                 liens[ptr]->sav_len=-1;       // taille invalide
  1923. #endif
  1924.                 //
  1925.               } else {  // oups erreur, plus de mΘmoire!!
  1926.                 printf("PANIC! : Not enough memory [%d]\n",__LINE__);
  1927.                 if (opt.errlog) {
  1928.                   fprintf(opt.errlog,"Not enough memory, can not re-allocate %d bytes"LF,(add_tab_alloc+1)*sizeof(lien_url));
  1929.                   test_flush;
  1930.                 }
  1931.                 //if (opt.getmode & 1) { if (fp) { fclose(fp); fp=NULL; } }
  1932.                 XH_uninit;    // dΘsallocation mΘmoire & buffers
  1933.                 return 0;
  1934.               } 
  1935.             } else {
  1936.               if (opt.errlog!=NULL) {
  1937.                 fspc(opt.errlog,"error"); fprintf(opt.errlog,"Can not remove old file %s"LF,urlfil);
  1938.                 test_flush;
  1939.               }
  1940.             }
  1941.           } else {
  1942.             if (opt.errlog!=NULL) {
  1943.               fspc(opt.errlog,"warning"); fprintf(opt.errlog,"Unexpected 412/416 error (%s) for %s%s"LF,r.msg,urladr,urlfil);
  1944.               test_flush;
  1945.             }
  1946.           }
  1947.         } else if (r.statuscode!=200) {
  1948.           int can_retry=0;
  1949.           
  1950.           // cas o∙ l'on peut reessayer
  1951.           // -2=timeout -3=rateout (interne α httrack)
  1952.           switch(r.statuscode) {
  1953.             //case -1: can_retry=1; break;
  1954.           case -2: if (opt.hostcontrol) {    // timeout et retry ΘpuisΘs
  1955.             if ((opt.hostcontrol & 1) && (liens[ptr]->retry<=0)) {
  1956.               if ((opt.debug>1) && (opt.log!=NULL)) {
  1957.                 fspc(opt.log,"debug"); fprintf(opt.log,"Link banned: %s%s"LF,urladr,urlfil); test_flush;
  1958.               }
  1959.               host_ban(&opt,liens,ptr,lien_tot,back,back_max,filters,filter_max,&filptr,jump_identification(urladr));
  1960.               if ((opt.debug>1) && (opt.log!=NULL)) {
  1961.                 fspc(opt.log,"debug"); fprintf(opt.log,"Info: previous log - link banned: %s%s"LF,urladr,urlfil); test_flush;
  1962.               }
  1963.             } else can_retry=1;
  1964.                    } else can_retry=1;
  1965.             break;
  1966.           case -3: if ((opt.hostcontrol) && (liens[ptr]->retry<=0)) {    // too slow
  1967.             if (opt.hostcontrol & 2) {
  1968.               if ((opt.debug>1) && (opt.log!=NULL)) {
  1969.                 fspc(opt.log,"debug"); fprintf(opt.log,"Link banned: %s%s"LF,urladr,urlfil); test_flush;
  1970.               }
  1971.               host_ban(&opt,liens,ptr,lien_tot,back,back_max,filters,filter_max,&filptr,jump_identification(urladr));
  1972.               if ((opt.debug>1) && (opt.log!=NULL)) {
  1973.                 fspc(opt.log,"debug"); fprintf(opt.log,"Info: previous log - link banned: %s%s"LF,urladr,urlfil); test_flush;
  1974.               }
  1975.             } else can_retry=1;
  1976.                    } else can_retry=1;
  1977.             break;
  1978.           case -4:            // connect closed
  1979.             can_retry=1;
  1980.             break;
  1981.           case -5:            // other (non fatal) error
  1982.             can_retry=1;
  1983.             break;
  1984.           case 408: case 409: case 500: case 502: case 504: can_retry=1;
  1985.             break;
  1986.           }
  1987.           
  1988.           if ( strcmp(liens[ptr]->fil,"/primary") ) {    // pas primary (page 0)
  1989.             if ((liens[ptr]->retry<=0) || (!can_retry) ) {  // retry ΘpuisΘs (ou retry impossible)
  1990.               if (opt.errlog) {
  1991.                 if ((opt.retry>0) && (can_retry)){
  1992.                   fspc(opt.errlog,"error"); 
  1993.                   fprintf(opt.errlog,"\"%s\" (%d) after %d retries at link %s%s (from %s%s)"LF,r.msg,r.statuscode,opt.retry,urladr,urlfil,liens[liens[ptr]->precedent]->adr,liens[liens[ptr]->precedent]->fil);
  1994.                 } else {
  1995.                   if (r.statuscode==-10) {    // test OK
  1996.                     if ((opt.debug>0) && (opt.errlog!=NULL)) {
  1997.                       fspc(opt.errlog,"info"); 
  1998.                       fprintf(opt.errlog,"Test OK at link %s%s (from %s%s)"LF,urladr,urlfil,liens[liens[ptr]->precedent]->adr,liens[liens[ptr]->precedent]->fil);
  1999.                     }
  2000.                   } else {
  2001.                     if (strcmp(urlfil,"/robots.txt")) {       // ne pas afficher d'infos sur robots.txt par dΘfaut
  2002.                       fspc(opt.errlog,"error"); 
  2003.                       fprintf(opt.errlog,"\"%s\" (%d) at link %s%s (from %s%s)"LF,r.msg,r.statuscode,urladr,urlfil,liens[liens[ptr]->precedent]->adr,liens[liens[ptr]->precedent]->fil);
  2004.                     } else {
  2005.                       if (opt.debug>1) {
  2006.                         fspc(opt.errlog,"info"); fprintf(opt.errlog,"No robots.txt rules at %s"LF,urladr);
  2007.                         test_flush;
  2008.                       }
  2009.                     }
  2010.                   }
  2011.                 }
  2012.                 test_flush;
  2013.               }
  2014.               
  2015.               // ici on teste si on doit enregistrer la page tout de mΩme
  2016.               if (opt.errpage) {
  2017.                 // NO error in trop level
  2018.                 // due to the "no connection -> previous restored" hack
  2019.                 if (liens[ptr]->precedent != 0) {
  2020.                   store_errpage=1;
  2021.                 }
  2022.               }
  2023.               
  2024.             } else {    // retry!!
  2025.               if (opt.debug>0) {  // on fera un alert si le retry Θchoue               
  2026.                 fspc(opt.errlog,"warning"); fprintf(opt.errlog,"Retry after error %d (%s) at link %s%s (from %s%s)"LF,r.statuscode,r.msg,urladr,urlfil,liens[liens[ptr]->precedent]->adr,liens[liens[ptr]->precedent]->fil);
  2027.                 test_flush;
  2028.               }
  2029.               // redemander fichier
  2030.               liens_record(urladr,urlfil,savename,"","");
  2031.               if (liens[lien_tot]!=NULL) {    // OK, pas d'erreur
  2032.                 liens[lien_tot]->testmode=liens[ptr]->testmode;          // mode test?
  2033.                 liens[lien_tot]->link_import=0;       // pas mode import
  2034.                 liens[lien_tot]->depth=liens[ptr]->depth;
  2035.                 liens[lien_tot]->pass2=max(liens[ptr]->pass2,numero_passe);
  2036.                 liens[lien_tot]->retry=liens[ptr]->retry-1;    // moins 1 retry!
  2037.                 liens[lien_tot]->premier=liens[ptr]->premier;
  2038.                 liens[lien_tot]->precedent=liens[ptr]->precedent;
  2039.                 lien_tot++;
  2040.               } else {  // oups erreur, plus de mΘmoire!!
  2041.                 printf("PANIC! : Not enough memory [%d]\n",__LINE__);
  2042.                 if (opt.errlog) {
  2043.                   fspc(opt.errlog,"panic"); 
  2044.                   fprintf(opt.errlog,"Not enough memory, can not re-allocate %d bytes"LF,(add_tab_alloc+1)*sizeof(lien_url));
  2045.                   test_flush;
  2046.                 }
  2047.                 //if (opt.getmode & 1) { if (fp) { fclose(fp); fp=NULL; } }
  2048.                 XH_uninit;    // dΘsallocation mΘmoire & buffers
  2049.                 return 0;
  2050.               } 
  2051.             }
  2052.           } else {
  2053.             if (opt.errlog) {
  2054.               if (opt.debug>1) {
  2055.                 fspc(opt.errlog,"info"); 
  2056.                 fprintf(opt.errlog,"Info: no robots.txt at %s%s"LF,urladr,urlfil);
  2057.               }
  2058.             }
  2059.           }
  2060.           if (!store_errpage) {
  2061.             if (r.adr) { freet(r.adr); r.adr=NULL; }  // dΘsalloc
  2062.             error=1;  // erreur!
  2063.           }
  2064.         }
  2065.         // FIN rattrapage des 301,302,307..
  2066.         // ------------------------------------------------------------
  2067.         
  2068.         
  2069.  
  2070.       }  // if !error
  2071.     }  // if !error
  2072.     
  2073.     if (!error) {  
  2074. #if DEBUG_SHOWTYPES
  2075.       if (strstr(REG,r.contenttype)==NULL) {
  2076.         strcat(REG,r.contenttype);
  2077.         strcat(REG,"\n");
  2078.         printf("%s\n",r.contenttype);
  2079.         io_flush;
  2080.       }
  2081. #endif
  2082.       
  2083.  
  2084.       // ------------------------------------------------------
  2085.       // ok, fichier chargΘ localement
  2086.       // ------------------------------------------------------
  2087.       
  2088.       // VΘrificateur d'intΘgritΘ
  2089.       #if DEBUG_CHECKINT
  2090.       {
  2091.         int i;
  2092.         for(i=0;i<back_max;i++) {
  2093.           char si[256];
  2094.           sprintf(si,"Test global aprΦs back_wait, index %d",i);
  2095.           _CHECKINT(&back[i],si)
  2096.         }
  2097.       }
  2098.       #endif
  2099.  
  2100.  
  2101.       /* info: updated */
  2102.       /*
  2103.       if (ptr>0) {
  2104.         // "mis α jour"
  2105.         if ((!r.notmodified) && (opt.is_update) && (!store_errpage)) {    // page modifiΘe
  2106.           if (strnotempty(savename)) {
  2107.             HTS_STAT.stat_updated_files++;
  2108.             if (opt.log!=NULL) {
  2109.               //if ((opt.debug>0) && (opt.log!=NULL)) {
  2110.               fspc(opt.log,"info"); fprintf(opt.log,"File updated: %s%s"LF,urladr,urlfil);
  2111.               test_flush;
  2112.             }
  2113.           }
  2114.         } else {
  2115.           if (!store_errpage) {
  2116.             if ( (opt.debug>0) && (opt.log!=NULL) ) {
  2117.               fspc(opt.log,"info"); fprintf(opt.log,"File recorded: %s%s"LF,urladr,urlfil);
  2118.               test_flush;
  2119.             }
  2120.           }
  2121.         }
  2122.       }
  2123.       */
  2124.       
  2125.       // ------------------------------------------------------
  2126.       // traitement (parsing)
  2127.       // ------------------------------------------------------
  2128.  
  2129.       // traiter
  2130.       if (
  2131.            ( (is_hypertext_mime(r.contenttype))   /* Is HTML or Js, .. */
  2132.              || (may_be_hypertext_mime(r.contenttype) && (r.adr) )  /* Is real media, .. */
  2133.            )
  2134.         && (liens[ptr]->depth>0)            /* Depth > 0 (recurse depth) */
  2135.         && (r.adr!=NULL)        /* HTML Data exists */
  2136.         && (r.size>0)           /* And not empty */
  2137.         && (!store_errpage)     /* Not an html error page */
  2138.         && (savename[0]!='\0')  /* Output filename exists */
  2139.         ) {    // ne traiter que le html si autorisΘ
  2140.         // -- -- -- --
  2141.         // Parsing HTML
  2142.         if (!error) {
  2143.           /* Info for wrappers */
  2144.           if ( (opt.debug>0) && (opt.log!=NULL) ) {
  2145.             fspc(opt.log,"info"); fprintf(opt.log,"engine: check-html: %s%s"LF,urladr,urlfil);
  2146.           }
  2147.           {
  2148.           // I'll have to segment this part
  2149. #include "htsparse.c"
  2150.           }
  2151.         }
  2152.         // Fin parsing HTML
  2153.         // -- -- -- --
  2154.  
  2155.  
  2156.       }  // si text/html
  2157.       // -- -- --
  2158.       else {    // sauver fichier quelconque
  2159.         // -- -- --
  2160.         // sauver fichier
  2161.  
  2162.  
  2163.         /* En cas d'erreur, vΘrifier que fichier d'erreur existe */
  2164.         if (strnotempty(savename) == 0) {           // chemin de sauvegarde existant
  2165.           if (strcmp(urlfil,"/robots.txt")==0) {    // pas robots.txt
  2166.             if (store_errpage) {                    // c'est une page d'erreur
  2167.               int create_html_warning=0;
  2168.               int create_gif_warning=0;
  2169.               switch (ishtml(urlfil)) {      /* pas fichier html */
  2170.               case 0:                        /* non html */
  2171.                 {
  2172.                   char buff[256];
  2173.                   guess_httptype(buff,urlfil);
  2174.                   if (strcmp(buff,"image/gif")==0)
  2175.                     create_gif_warning=1;
  2176.                 }
  2177.                 break;
  2178.               case 1:                        /* html */
  2179.                 if (!r.adr) {
  2180.                 }
  2181.                 break;
  2182.               default:                       /* don't know.. */
  2183.                 break;    
  2184.               }
  2185.               /* CrΘer message d'erreur ? */
  2186.               if (create_html_warning) {
  2187.                 char* adr=(char*)malloct(strlen(HTS_DATA_ERROR_HTML)+1100);
  2188.                 if ( (opt.debug>0) && (opt.log!=NULL) ) {
  2189.                   fspc(opt.log,"info"); fprintf(opt.log,"Creating HTML warning file (%s)"LF,r.msg);
  2190.                   test_flush;
  2191.                 }
  2192.                 if (adr) {
  2193.                   if (r.adr) {
  2194.                     freet(r.adr);
  2195.                     r.adr=NULL;
  2196.                   }
  2197.                   sprintf(adr,HTS_DATA_ERROR_HTML,r.msg);
  2198.                   r.adr=adr;
  2199.                 }
  2200.               } else if (create_gif_warning) {
  2201.                 char* adr=(char*)malloct(HTS_DATA_UNKNOWN_GIF_LEN);
  2202.                 if ( (opt.debug>0) && (opt.log!=NULL) ) {
  2203.                   fspc(opt.log,"info"); fprintf(opt.log,"Creating GIF dummy file (%s)"LF,r.msg);
  2204.                   test_flush;
  2205.                 }
  2206.                 if (r.adr) {
  2207.                   freet(r.adr);
  2208.                   r.adr=NULL;
  2209.                 }
  2210.                 bcopy(HTS_DATA_UNKNOWN_GIF,adr,HTS_DATA_UNKNOWN_GIF_LEN);
  2211.                 r.adr=adr;
  2212.               }
  2213.             }
  2214.           }
  2215.         }
  2216.  
  2217.         if (strnotempty(savename) == 0) {    // pas de chemin de sauvegarde
  2218.           if (strcmp(urlfil,"/robots.txt")==0) {    // robots.txt
  2219.             if (r.adr) {
  2220.               int bptr=0;
  2221.               char line[256];
  2222.               char buff[8192];
  2223.               char infobuff[8192];
  2224.               int record=0;
  2225.               line[0]='\0'; buff[0]='\0'; infobuff[0]='\0';
  2226.               //
  2227. #if DEBUG_ROBOTS
  2228.               printf("robots.txt dump:\n%s\n",r.adr);
  2229. #endif
  2230.               do {
  2231.                 bptr+=binput(r.adr+bptr,line,200);
  2232.                 if (strfield(line,"user-agent:")) {
  2233.                   char* a;
  2234.                   a=line+11;
  2235.                   while(*a==' ') a++;    // sauter espace(s)
  2236.                   if (*a == '*') {
  2237.                     if (record != 2)
  2238.                       record=1;    // c pour nous
  2239.                   } else if (strfield(a,"httrack")) {
  2240.                     buff[0]='\0';      // re-enregistrer
  2241.                     infobuff[0]='\0';
  2242.                     record=2;          // locked
  2243. #if DEBUG_ROBOTS
  2244.                     printf("explicit disallow for httrack\n");
  2245. #endif
  2246.                   }
  2247.                   else record=0;
  2248.                 } else if (record) {
  2249.                   if (strfield(line,"disallow:")) {
  2250.                     char* a;
  2251.                     a=strchr(line,'#');
  2252.                     if (a) *a='\0';
  2253.                     while((line[strlen(line)-1]==' ') || (line[strlen(line)-1]==10) || (line[strlen(line)-1]==13))
  2254.                       line[strlen(line)-1]='\0';   // supprimer espaces
  2255.                     a=line+9;
  2256.                     while((*a==' ') || (*a==10) || (*a==13))
  2257.                       a++;    // sauter espace(s)
  2258.                     if (strnotempty(a)) {
  2259.                       if (strcmp(a,"/")) {      /* ignoring disallow: / */
  2260.                         strcat(buff,a);
  2261.                         strcat(buff,"\n");
  2262.                         if (strnotempty(infobuff)) strcat(infobuff,", ");
  2263.                         strcat(infobuff,a);
  2264.                       } else {
  2265.                         if (opt.errlog!=NULL) {
  2266.                           fspc(opt.errlog,"info"); fprintf(opt.errlog,"Note: %s robots.txt rules are too restrictive, ignoring /"LF,urladr);
  2267.                           test_flush;
  2268.                         }
  2269.                       }
  2270.                     }
  2271.                   }
  2272.                 }
  2273.               } while( (bptr<r.size) && (strlen(buff)<4096) );
  2274.               if (strnotempty(buff)) {
  2275.                 checkrobots_set(&robots,urladr,buff);
  2276.                 if (opt.log!=NULL) {
  2277.                   if (opt.log != opt.errlog) {
  2278.                     fspc(opt.log,"info"); fprintf(opt.log,"Note: robots.txt forbidden links for %s are: %s"LF,urladr,infobuff);
  2279.                     test_flush;
  2280.                   } 
  2281.                 }
  2282.                 if (opt.errlog!=NULL) {
  2283.                   fspc(opt.errlog,"info"); fprintf(opt.errlog,"Note: due to %s remote robots.txt rules, links begining with these path will be forbidden: %s (see in the options to disable this)"LF,urladr,infobuff);
  2284.                   test_flush;
  2285.                 }
  2286.               }
  2287.             }
  2288.           }
  2289.         } else if (r.is_write) {    // dΘja sauvΘ sur disque
  2290.           /*
  2291.           if (!ishttperror(r.statuscode))
  2292.             HTS_STAT.stat_files++;
  2293.           HTS_STAT.stat_bytes+=r.size;
  2294.           */
  2295.           //printf("ok......\n");
  2296.         } else {
  2297.           // Si on doit sauver une page HTML sans la scanner, cela signifie que le niveau de
  2298.           // rΘcursion nous en empΩche
  2299.           // Dans ce cas on met un fichier indiquant ce fait
  2300.           // Si par la suite on doit retraiter ce fichier avec un niveau de rΘcursion plus
  2301.           // fort, on supprimera le readme, et on scannera le fichier html!
  2302.           // note: sautΘ si store_errpage (cαd si page d'erreur, non α scanner!)
  2303.           if ( (is_hypertext_mime(r.contenttype)) && (!store_errpage) && (r.size>0)) {  // c'est du html!!
  2304.             char tempo[HTS_URLMAXSIZE*2];
  2305.             FILE* fp;
  2306.             tempo[0]='\0';
  2307.             strcpy(tempo,savename);
  2308.             strcat(tempo,".readme");
  2309.             
  2310. #if HTS_DOSNAME
  2311.             // remplacer / par des slash arriΦre
  2312.             {
  2313.               int i=0;
  2314.               while(tempo[i]) {
  2315.                 if (tempo[i]=='/')
  2316.                   tempo[i]='\\';
  2317.                 i++;
  2318.               } 
  2319.             } 
  2320.             // a partir d'ici le slash devient antislash
  2321. #endif
  2322.             
  2323.             if ((fp=fopen(tempo,"wb"))!=NULL) {
  2324.               fprintf(fp,"Info-file generated by HTTrack Website Copier "HTTRACK_VERSION""CRLF""CRLF);
  2325.               fprintf(fp,"The file %s has not been scanned by HTS"CRLF,savename);
  2326.               fprintf(fp,"Some links contained in it may be unreachable locally."CRLF);
  2327.               fprintf(fp,"If you want to get these files, you have to set an upper recurse level, ");
  2328.               fprintf(fp,"and to rescan the URL."CRLF);
  2329.               fclose(fp);
  2330. #if HTS_WIN==0
  2331.               chmod(tempo,HTS_ACCESS_FILE);      
  2332. #endif
  2333.               usercommand(0,NULL,antislash(tempo));
  2334.             }
  2335.             
  2336.             
  2337.             if ( (opt.debug>0) && (opt.errlog!=NULL) ) {
  2338.               fspc(opt.errlog,"warning"); fprintf(opt.errlog,"Warning: store %s without scan: %s"LF,r.contenttype,savename);
  2339.               test_flush;
  2340.             }
  2341.           } else {
  2342.             if ((opt.getmode & 2)!=0) {    // ok autorisΘ
  2343.               if ( (opt.debug>1) && (opt.log!=NULL) ) {
  2344.                 fspc(opt.log,"debug"); fprintf(opt.log,"Store %s: %s"LF,r.contenttype,savename);
  2345.                 test_flush;
  2346.               }
  2347.             } else {    // lien non autorisΘ! (ex: cgi-bin en html)
  2348.               if ((opt.debug>1) && (opt.log!=NULL)) {
  2349.                 fspc(opt.log,"debug"); fprintf(opt.log,"non-html file ignored after upload at %s : %s"LF,urladr,urlfil);
  2350.                 test_flush;
  2351.               } 
  2352.               freet(r.adr); r.adr=NULL;
  2353.             }
  2354.           }
  2355.           
  2356.           //printf("extern=%s\n",r.contenttype);
  2357.  
  2358.           // ATTENTION C'EST ICI QU'ON SAUVE LE FICHIER!!          
  2359.           if (r.adr) {
  2360.             if (filesave(r.adr,(int)r.size,savename)!=0) {
  2361.               if (opt.errlog) {   
  2362.                 fspc(opt.errlog,"error"); fprintf(opt.errlog,"Unable to save file %s"LF,savename);
  2363.                 test_flush;
  2364.               }
  2365.             } else {
  2366.               /*
  2367.               if (!ishttperror(r.statuscode))
  2368.                 HTS_STAT.stat_files++;
  2369.               HTS_STAT.stat_bytes+=r.size;
  2370.               */
  2371.             }
  2372.           }
  2373.           
  2374.         }
  2375.   
  2376.  
  2377.         /* Parsing of other media types (java, ram..) */
  2378.         /*
  2379.         if (strfield2(r.contenttype,"audio/x-pn-realaudio")) {
  2380.           if ((opt.debug>1) && (opt.log!=NULL)) {
  2381.             fspc(opt.log,"debug"); fprintf(opt.log,"(Real Media): parsing %s"LF,savename); test_flush;
  2382.           }
  2383.           if (fexist(savename)) {   // ok, existe bien!
  2384.             FILE* fp=fopen(savename,"r+b");
  2385.             if (fp) {
  2386.               if (!fseek(fp,0,SEEK_SET)) {
  2387.                 char line[HTS_URLMAXSIZE*2];
  2388.                 linput(fp,line,HTS_URLMAXSIZE);
  2389.                 if (strnotempty(line)) {
  2390.                   if ((opt.debug>1) && (opt.log!=NULL)) {
  2391.                     fspc(opt.log,"debug"); fprintf(opt.log,"(Real Media): detected %s"LF,line); test_flush;
  2392.                   }
  2393.                 }
  2394.               }
  2395.               fclose(fp);
  2396.             }
  2397.           }
  2398.         } else */
  2399.         if (opt.parsejava) {
  2400.           if (strlen(savename)>6) {  // fichier.class
  2401.             if (strfield(savename+strlen(savename)-6,".class")) {  // ok c'est une classe
  2402.               if (fexist(savename)) {   // ok, existe bien!
  2403.                 char err_msg[1100];
  2404.                 int r;
  2405.                 err_msg[0]='\0';
  2406.                 
  2407.                 //##char* buffer;
  2408.                 // JavaParsing f34R!
  2409.                 if ((opt.debug>1) && (opt.log!=NULL)) {
  2410.                   fspc(opt.log,"debug"); fprintf(opt.log,"(JavaClass catch file): parsing %s"LF,savename); test_flush;
  2411.                 }
  2412.                 
  2413.                 //##buffer=(char*) malloct(32768);
  2414.                 //##if (buffer) {
  2415.                 //
  2416.                 //##strcpy(buffer,"$BUFFER$");
  2417.                 //##hts_add_file(buffer);    // dΘclarer buffer
  2418.                 while(hts_add_file(NULL,-1) >= 0);   // clear chain
  2419.                 
  2420.                 r=hts_parse_java(savename,(char*) &err_msg);  // parsing
  2421.                 if (!r) {    // error
  2422.                   if (opt.errlog) {   
  2423.                     fspc(opt.errlog,"error"); fprintf(opt.errlog,"Unable to parse java file %s : %s"LF,savename,err_msg);
  2424.                     test_flush;
  2425.                   }
  2426.                 } else {  // ok
  2427.                   char adr[HTS_URLMAXSIZE*2],fil[HTS_URLMAXSIZE*2],save[HTS_URLMAXSIZE*2];  // nom du fichier α sauver dans la boucle
  2428.                   char codebase[HTS_URLMAXSIZE*2];                  // codebase classe java
  2429.                   char lien[HTS_URLMAXSIZE*2];
  2430.                   //##char* a;
  2431.                   int file_position;
  2432.                   int pass_fix,prio_fix;
  2433.                   codebase[0]='\0';
  2434.                   //
  2435.                   
  2436.                   if ((opt.debug>1) && (opt.log!=NULL)) {
  2437.                     fspc(opt.log,"debug"); fprintf(opt.log,"(JavaClass catch file): parsing finished, now copying links.."LF); test_flush;
  2438.                   }
  2439.                   // recopie de "creer le lien"
  2440.                   //
  2441.                   
  2442.                   // adr = c'est la mΩme
  2443.                   // fil et save: save2 et fil2
  2444.                   prio_fix=maximum(liens[ptr]->depth-1,0);
  2445.                   pass_fix=max(liens[ptr]->pass2,numero_passe);
  2446.                   if (liens[ptr]->cod) strcpy(codebase,liens[ptr]->cod);       // codebase valable pour tt les classes descendantes
  2447.                   if (strnotempty(codebase)==0) {    // pas de codebase, construire
  2448.                     char* a;
  2449.                     strcpy(codebase,liens[ptr]->fil);
  2450.                     a=codebase+strlen(codebase)-1;
  2451.                     while((*a) && (*a!='/') && ((int) a > (int) codebase)) a--;
  2452.                     if (*a=='/')
  2453.                       *(a+1)='\0';    // couper
  2454.                   } else {    // couper http:// Θventuel
  2455.                     if (strfield(codebase,"http://")) {
  2456.                       char tempo[HTS_URLMAXSIZE*2];
  2457.                       char* a=codebase+7;
  2458.                       a=strchr(a,'/');    // aprΦs host
  2459.                       if (a) {  // ** msg erreur et vΘrifier?
  2460.                         strcpy(tempo,a);
  2461.                         strcpy(codebase,tempo);    // couper host
  2462.                       } else {
  2463.                         if (opt.errlog) {   
  2464.                           fprintf(opt.errlog,"Unexpected strstr error in base %s"LF,codebase);
  2465.                           test_flush;
  2466.                         }
  2467.                       }
  2468.                     }
  2469.                   }
  2470.                   //##a=buffer;
  2471.                   //##strcat(buffer,"&");  // fin du buffer
  2472.                   if (!((int) strlen(codebase)<HTS_URLMAXSIZE)) {    // trop long
  2473.                     if (opt.errlog) {   
  2474.                       fprintf(opt.errlog,"Codebase too long, parsing skipped (%s)"LF,codebase);
  2475.                       test_flush;
  2476.                     }
  2477.                     //##a=NULL;
  2478.                     while(hts_add_file(NULL,-1) >= 0);   // clear chain
  2479.                   }
  2480.                   while ( (file_position=hts_add_file(lien,-1)) >= 0 ) {
  2481.                     int dejafait=0;
  2482.                     /* //##
  2483.                     char* b;
  2484.                     
  2485.                      // prochain fichier α noter!
  2486.                      lien[0]='\0';
  2487.                      b=strchr(a,'&');  // marqueur de fin de chaine (voir hts_add_file)
  2488.                      if (b) {
  2489.                      if ( ( ((int) b-(int) a) + strlen(codebase)) < HTS_URLMAXSIZE)
  2490.                      strncat(lien,a,(int) b-(int) a);    // nom du fichier
  2491.                      else {
  2492.                      if (opt.errlog) {   
  2493.                      fprintf(opt.errlog,"Error: Java-Parser generated link that exceeds %d bytes"LF,HTS_URLMAXSIZE);
  2494.                      test_flush;
  2495.                      }
  2496.                      }
  2497.                      } else a=NULL;
  2498.                      
  2499.                       if (strnotempty(lien)==0) a=NULL;  // fin
  2500.                       if (a)
  2501.                       a=b+1;
  2502.                     */
  2503.                     
  2504.                     if (strnotempty(lien)) {
  2505.                       
  2506.                       // calculer les chemins et noms de sauvegarde
  2507.                       if (ident_url_relatif(lien,urladr,codebase,adr,fil)>=0) { // reformage selon chemin
  2508.                         int r;
  2509.                         
  2510.                         //  patcher opt pour garder structure originale!! (on ne patche pas les noms dans la classe java!)
  2511.                         //##if (!strstr(lien,"://")) {         // PAS tester les http://.. inutile (on ne va pas patcher le binaire :-( )
  2512.                         if (1) {
  2513.                           char tempo[HTS_URLMAXSIZE*2];
  2514.                           int a,b;
  2515.                           tempo[0]='\0';
  2516.                           a=opt.savename_type;
  2517.                           b=opt.savename_83;
  2518.                           opt.savename_type=0;
  2519.                           opt.savename_83=0;
  2520.                           // note: adr,fil peuvent Ωtre patchΘs
  2521.                           r=url_savename(adr,fil,save,NULL,NULL,NULL,NULL,&opt,liens,lien_tot,back,back_max,&cache,&hash,ptr,numero_passe);
  2522.                           opt.savename_type=a;
  2523.                           opt.savename_83=b;
  2524.                           if (r != -1) {
  2525.                             if (savename) {
  2526.                               if (lienrelatif(tempo,save,savename)==0) {
  2527.                                 if ((opt.debug>1) && (opt.log!=NULL)) {
  2528.                                   fspc(opt.log,"debug"); fprintf(opt.log,"(JavaClass catch file): relative link at %s build with %s and %s: %s"LF,adr,save,savename,tempo);
  2529.                                   test_flush;
  2530.                                 }
  2531.                                 //
  2532.                                 // xxc xxc xxc xxc TODO java:
  2533.                                 // rebuild the java class with patched strings...
  2534.                                 //
  2535.                                 if (strlen(tempo)<=strlen(lien)) {
  2536.                                   FILE* fp=fopen(savename,"r+b");
  2537.                                   if (fp) {
  2538.                                     if (!fseek(fp,file_position,SEEK_SET)) {
  2539.                                       //unsigned short int string_length=strlen(tempo);
  2540.                                       //fwrite(&valint,sizeof(string_length),1,fp);
  2541.                                       // xxc xxc ARGH! SI la taille est <, dΘcaler le code ?!
  2542.                                     } else {
  2543.                                       if (opt.log!=NULL) {
  2544.                                         fspc(opt.log,"debug"); fprintf(opt.log,"(JavaClass catch file): unable to patch: %s"LF,savename);
  2545.                                         test_flush;
  2546.                                       }
  2547.                                     }
  2548.                                     fclose(fp);
  2549.                                   } else {
  2550.                                     if (opt.log!=NULL) {
  2551.                                       fspc(opt.log,"debug"); fprintf(opt.log,"(JavaClass catch file): unable to open: %s"LF,savename);
  2552.                                       test_flush;
  2553.                                     }
  2554.                                   }
  2555.                                 } else {
  2556.                                   if (opt.log!=NULL) {
  2557.                                     fspc(opt.log,"debug"); fprintf(opt.log,"(JavaClass catch file): link too long, unable to write it: %s"LF,tempo);
  2558.                                     test_flush;
  2559.                                   }
  2560.                                 }
  2561.                               }
  2562.                             }
  2563.                           }
  2564.                         } else {
  2565.                           if ((opt.debug>1) && (opt.log!=NULL)) {
  2566.                             fspc(opt.log,"debug"); fprintf(opt.log,"(JavaClass catch file): file not caught: %s"LF,lien); test_flush;
  2567.                           }
  2568.                           r=-1;
  2569.                         }
  2570.                         //
  2571.                         if (r != -1) {
  2572.                           if ((opt.debug>1) && (opt.log!=NULL)) {
  2573.                             fspc(opt.log,"debug"); fprintf(opt.log,"(JavaClass catch file): %s%s -> %s (base %s)"LF,adr,fil,save,codebase); test_flush;
  2574.                           }
  2575.                           
  2576.                           // modifiΘ par rapport α l'autre version (cf prio_fix notamment et save2)
  2577.                           
  2578.                           // vΘrifier que le lien n'a pas dΘja ΘtΘ notΘ
  2579.                           // si c'est le cas, alors il faut s'assurer que la prioritΘ associΘe
  2580.                           // au fichier est la plus grande des deux prioritΘs
  2581.                           //
  2582.                           // On part de la fin et on essaye de se presser (Θconomise temps machine)
  2583. #if HTS_HASH
  2584.                           {
  2585.                             int i=hash_read(&hash,save,"",0);      // lecture type 0 (sav)
  2586.                             if (i>=0) {
  2587.                               liens[i]->depth=maximum(liens[i]->depth,prio_fix);
  2588.                               dejafait=1;
  2589.                             }
  2590.                           }
  2591. #else
  2592.                           {
  2593.                             register int l;
  2594.                             register int i;
  2595.                             l=strlen(save);
  2596.                             for(i=lien_tot-1;(i>=0) && (dejafait==0);i--) {
  2597.                               if (liens[i]->sav_len==l) {    // mΩme taille de chaεne
  2598.                                 if (strcmp(liens[i]->sav,save)==0) {    // existe dΘja
  2599.                                   liens[i]->depth=maximum(liens[i]->depth,prio_fix);
  2600.                                   dejafait=1;
  2601.                                 }
  2602.                               }
  2603.                             }
  2604.                           }
  2605. #endif
  2606.                           
  2607.                           
  2608.                           if (!dejafait) {
  2609.                             //
  2610.                             // >>>> CREER LE LIEN JAVA <<<<
  2611.                             
  2612.                             // enregistrer fichier de java (MACRO)
  2613.                             liens_record(adr,fil,save,"","");
  2614.                             if (liens[lien_tot]==NULL) {  // erreur, pas de place rΘservΘe
  2615.                               printf("PANIC! : Not enough memory [%d]\n",__LINE__);
  2616.                               if (opt.errlog) { 
  2617.                                 fprintf(opt.errlog,"Not enough memory, can not re-allocate %d bytes"LF,(add_tab_alloc+1)*sizeof(lien_url));
  2618.                                 test_flush;
  2619.                               }
  2620.                               // if ((opt.getmode & 1) && (ptr>0)) { if (fp) { fclose(fp); fp=NULL; } }
  2621.                               XH_extuninit;    // dΘsallocation mΘmoire & buffers
  2622.                               return 0;
  2623.                             }  
  2624.                             
  2625.                             // mode test?                          
  2626.                             liens[lien_tot]->testmode=0;          // pas mode test
  2627.                             
  2628.                             liens[lien_tot]->link_import=0;       // pas mode import
  2629.                             
  2630.                             // Θcrire autres paramΦtres de la structure-lien
  2631.                             //if (meme_adresse)                                 
  2632.                             liens[lien_tot]->premier=liens[ptr]->premier;
  2633.                             //else    // sinon l'objet pΦre est le prΘcΘdent lui mΩme
  2634.                             //  liens[lien_tot]->premier=ptr;
  2635.                             
  2636.                             liens[lien_tot]->precedent=ptr;
  2637.                             // noter la prioritΘ
  2638.                             liens[lien_tot]->depth=prio_fix;
  2639.                             liens[lien_tot]->pass2=max(pass_fix,numero_passe);
  2640.                             liens[lien_tot]->retry=opt.retry;
  2641.                             
  2642.                             //strcpy(liens[lien_tot]->adr,adr);
  2643.                             //strcpy(liens[lien_tot]->fil,fil);
  2644.                             //strcpy(liens[lien_tot]->sav,save); 
  2645.                             if ((opt.debug>1) && (opt.log!=NULL)) {
  2646.                               fspc(opt.log,"debug"); fprintf(opt.log,"(JavaClass catch file): OK, NOTE: %s%s -> %s"LF,liens[lien_tot]->adr,liens[lien_tot]->fil,liens[lien_tot]->sav);
  2647.                               test_flush;
  2648.                             }
  2649.                             
  2650.                             lien_tot++;  // UN LIEN DE PLUS
  2651.                           }
  2652.                         }      
  2653.                         }  
  2654.                         
  2655.                       }  
  2656.                     }
  2657.                     
  2658.                   }
  2659.                   //##// effacer buffer temporaire
  2660.                   //##if (buffer) freet(buffer); buffer=NULL;
  2661.                   //##}  // if buffer
  2662.               }  // if exist
  2663.             }  // if .class
  2664.           }  // if strlen-savename
  2665.         }  // if opt.parsejava
  2666.         
  2667.         
  2668.         
  2669.       }  // text/html ou autre
  2670.       
  2671.     }  // if !error
  2672.     
  2673.  
  2674. jump_if_done:
  2675.     // libΘrer les liens
  2676.     if (r.adr) { freet(r.adr); r.adr=NULL; }   // libΘrer la mΘmoire!
  2677.     
  2678.     // prochain lien
  2679.     ptr++;
  2680.     
  2681.     // faut-il sauter le(s) lien(s) suivant(s)? (fichiers images α passer aprΦs les html)
  2682.     if (opt.getmode & 4) {    // sauver les non html aprΦs
  2683.       // sauter les fichiers selon la passe
  2684.       if (!numero_passe) {
  2685.         while((ptr<lien_tot)?(   liens[ptr]->pass2):0) ptr++;
  2686.       } else {
  2687.         while((ptr<lien_tot)?( ! liens[ptr]->pass2):0) ptr++;
  2688.       }
  2689.       if (ptr>=lien_tot) {     // fin de boucle
  2690.         if (!numero_passe) { // premiΦre boucle
  2691.           if ((opt.debug>1) && (opt.log!=NULL)) {
  2692.             fprintf(opt.log,LF"Now getting non-html files..."LF);
  2693.             test_flush;
  2694.           }
  2695.           numero_passe=1;   // seconde boucle
  2696.           ptr=0;
  2697.           // prochain pass2
  2698.           while((ptr<lien_tot)?(!liens[ptr]->pass2):0) ptr++;
  2699.           
  2700.           //printf("first link==%d\n");
  2701.           
  2702.         }
  2703.       }  
  2704.     }
  2705.         
  2706.     // a-t-on dΘpassΘ le quota?
  2707.     if ((opt.maxsite>0) && (HTS_STAT.stat_bytes>=opt.maxsite)) {
  2708.       if (opt.errlog) {
  2709.         fprintf(opt.errlog,"More than %d bytes have been transfered.. giving up"LF,opt.maxsite);
  2710.         test_flush;
  2711.       } 
  2712.       ptr=lien_tot;
  2713.     } else if ((opt.maxtime>0) && ((time_local()-HTS_STAT.stat_timestart)>opt.maxtime)) {            
  2714.       if (opt.errlog) {
  2715.         fprintf(opt.errlog,"More than %d seconds passed.. giving up"LF,opt.maxtime);
  2716.         test_flush;
  2717.       } 
  2718.       ptr=lien_tot;
  2719.     } else if (exit_xh) {  // sortir
  2720.       if (opt.errlog) {
  2721.         fspc(opt.errlog,"info"); fprintf(opt.errlog,"Exit requested by shell or user"LF);
  2722.         test_flush;
  2723.       } 
  2724.       ptr=lien_tot;
  2725.     }
  2726.   } while(ptr<lien_tot);
  2727.   //
  2728.   //
  2729.   //
  2730.  
  2731.  
  2732.   // no data transfered, no data saved
  2733.   // we assume that something was bad (no connection)
  2734.   // just backup old cache and restore everything
  2735.   if ( (HTS_STAT.stat_files == 0) && (HTS_STAT.HTS_TOTAL_RECV < 2048) ) {
  2736.     if (opt.errlog) {
  2737.       fspc(opt.errlog,"info"); fprintf(opt.errlog,"No data seems to have been transfered during this session! : restoring previous one!"LF);
  2738.       test_flush;
  2739.     } 
  2740.     XH_uninit;
  2741.     if ( (fexist(fconcat(opt.path_log,"hts-cache/old.dat"))) && (fexist(fconcat(opt.path_log,"hts-cache/old.ndx"))) ) {
  2742.       remove(fconcat(opt.path_log,"hts-cache/new.dat"));
  2743.       remove(fconcat(opt.path_log,"hts-cache/new.ndx"));
  2744.       remove(fconcat(opt.path_log,"hts-cache/new.lst"));
  2745.       rename(fconcat(opt.path_log,"hts-cache/old.dat"),fconcat(opt.path_log,"hts-cache/new.dat"));
  2746.       rename(fconcat(opt.path_log,"hts-cache/old.ndx"),fconcat(opt.path_log,"hts-cache/new.ndx"));
  2747.       rename(fconcat(opt.path_log,"hts-cache/old.lst"),fconcat(opt.path_log,"hts-cache/new.lst"));
  2748.     }
  2749.     exit_xh=2;        /* interrupted (no connection detected) */
  2750.     return 1;
  2751.   }
  2752.  
  2753.  
  2754.   // purger!
  2755.   if (opt.delete_old) {
  2756.     if (cache.lst) {
  2757.       FILE *old_lst,*new_lst;
  2758.       //
  2759. #if HTS_ANALYSTE
  2760.       _hts_in_html_parsing=3;
  2761. #endif
  2762.       //
  2763.       fclose(cache.lst); cache.lst=NULL;
  2764.       old_lst=fopen(fconcat(opt.path_log,"hts-cache/old.lst"),"rb");
  2765.       if (old_lst) {
  2766.         LLint sz=fsize(fconcat(opt.path_log,"hts-cache/new.lst"));
  2767.         new_lst=fopen(fconcat(opt.path_log,"hts-cache/new.lst"),"rb");
  2768.         if ((new_lst) && (sz>0)) {
  2769.           char* adr=(char*) malloct((INTsys)sz);
  2770.           if (adr) {
  2771.             if ((int) fread(adr,1,(INTsys)sz,new_lst) == sz) {
  2772.               char line[1100];
  2773.               int purge=0;
  2774.               while(!feof(old_lst)) {
  2775.                 linput(old_lst,line,1000);
  2776.                 if (!strstr(adr,line)) {    // fichier non trouvΘ dans le nouveau?
  2777.                   char file[HTS_URLMAXSIZE*2];
  2778.                   strcpy(file,opt.path_html);
  2779.                   strcat(file,line+1);
  2780.                   file[strlen(file)-1]='\0';
  2781.                   if (fexist(file)) {       // toujours sur disque: virer
  2782.                     if (opt.log) {
  2783.                       fspc(opt.log,"info"); fprintf(opt.log,"Purging %s"LF,file);
  2784.                     }
  2785.                     remove(file); purge=1;
  2786.                   }
  2787.                 }
  2788.               }
  2789.               {
  2790.                 fseek(old_lst,0,SEEK_SET);
  2791.                 while(!feof(old_lst)) {
  2792.                   linput(old_lst,line,1000);
  2793.                   while(strnotempty(line) && (line[strlen(line)-1]!='/') && (line[strlen(line)-1]!='\\')) {
  2794.                     line[strlen(line)-1]='\0';
  2795.                   }
  2796.                   if (strnotempty(line))
  2797.                     line[strlen(line)-1]='\0';
  2798.                   if (strnotempty(line))
  2799.                     if (!strstr(adr,line)) {    // non trouvΘ?
  2800.                       char file[HTS_URLMAXSIZE*2];
  2801.                       strcpy(file,opt.path_html);
  2802.                       strcat(file,line+1);
  2803.                       while ((strnotempty(file)) && (rmdir(file)==0)) {    // ok, ΘliminΘ (existait)
  2804.                         purge=1;
  2805.                         if (opt.log) {
  2806.                           fspc(opt.log,"info"); fprintf(opt.log,"Purging directory %s/"LF,file);
  2807.                           while(strnotempty(file) && (file[strlen(file)-1]!='/') && (file[strlen(file)-1]!='\\')) {
  2808.                             file[strlen(file)-1]='\0';
  2809.                           }
  2810.                           if (strnotempty(file))
  2811.                             file[strlen(file)-1]='\0';
  2812.                         }
  2813.                       }
  2814.                     }
  2815.                 }
  2816.               }
  2817.               //
  2818.               if (!purge) {
  2819.                 if (opt.log) {
  2820.                   fprintf(opt.log,"No files purged"LF);
  2821.                 }
  2822.               }
  2823.             }
  2824.             freet(adr);
  2825.           }
  2826.           fclose(new_lst);
  2827.         }
  2828.         fclose(old_lst);
  2829.       }
  2830.       //
  2831. #if HTS_ANALYSTE
  2832.       _hts_in_html_parsing=0;
  2833. #endif
  2834.     }
  2835.   }
  2836.   // fin purge!
  2837.   
  2838.  
  2839.   // Indexation
  2840.   if (opt.kindex)
  2841.     index_finish(opt.path_html);
  2842.  
  2843.   // afficher rΘsumΘ dans log
  2844.   if (opt.log!=NULL) {
  2845.     int error   = fspc(NULL,"error");
  2846.     int warning = fspc(NULL,"warning");
  2847.     int info    = fspc(NULL,"info");
  2848.     char htstime[256];
  2849.     // int n=(int) (stat_loaded/(time_local()-HTS_STAT.stat_timestart));
  2850.     int n=(int) (HTS_STAT.HTS_TOTAL_RECV/(max(1,time_local()-HTS_STAT.stat_timestart)));
  2851.     
  2852.     sec2str(htstime,time_local()-HTS_STAT.stat_timestart);
  2853.     //fprintf(opt.log,LF"HTS-mirror complete in %s : %d links scanned, %d files written (%d bytes overall) [%d bytes received at %d bytes/sec]"LF,htstime,lien_tot-1,HTS_STAT.stat_files,stat_bytes,stat_loaded,n);
  2854.     fprintf(opt.log,LF"HTTrack mirror complete in %s : %d links scanned, %d files written (%d bytes overall) [%d bytes received at %d bytes/sec]",htstime,(int)lien_tot-1,(int)HTS_STAT.stat_files,(int)HTS_STAT.stat_bytes,(int)HTS_STAT.HTS_TOTAL_RECV,(int)n);
  2855.     if (HTS_STAT.total_packed) {
  2856.       int packed_ratio=(int)((LLint)(HTS_STAT.total_packed*100)/HTS_STAT.total_unpacked);
  2857.       fprintf(opt.log,", "LLintP" bytes transfered using HTTP compression in %d files, ratio %d%%",HTS_STAT.total_unpacked,HTS_STAT.total_packedfiles,packed_ratio);
  2858.     }
  2859.     fprintf(opt.log,LF);
  2860.     if (error)
  2861.       fprintf(opt.log,"(%d errors, %d warnings, %d messages)"LF,error,warning,info);
  2862.     else
  2863.       fprintf(opt.log,"(No errors, %d warnings, %d messages)"LF,warning,info);
  2864.     test_flush;
  2865.   }
  2866. #if DEBUG_HASH
  2867.   // noter les collisions
  2868.   {
  2869.     int i;
  2870.     int empty1=0,empty2=0,empty3=0;
  2871.     for(i=0;i<HTS_HASH_SIZE;i++) {
  2872.       if (hash.hash[0][i] == -1)
  2873.         empty1++;
  2874.       if (hash.hash[1][i] == -1)
  2875.         empty2++;
  2876.       if (hash.hash[2][i] == -1)
  2877.         empty3++;
  2878.     }
  2879.     printf("\n");
  2880.     printf("Debug info: Hash-table report\n");
  2881.     printf("Number of files entered:   %d\n",hashnumber);
  2882.     printf("Table size:                %d\n",HTS_HASH_SIZE);
  2883.     printf("\n");
  2884.     printf("Longest chain sav:              %d, empty: %d\n",longest_hash[0],empty1);
  2885.     printf("Longest chain adr,fil:          %d, empty: %d\n",longest_hash[1],empty2);
  2886.     printf("Longest chain former_adr/fil:   %d, empty: %d\n",longest_hash[2],empty3);
  2887.     printf("\n");
  2888.   }
  2889. #endif    
  2890.   // fin afficher rΘsumΘ dans log
  2891.   
  2892.   // dΘsallocation mΘmoire & buffers  
  2893.  
  2894.   XH_uninit    
  2895.  
  2896.   return 1;    // OK
  2897. }
  2898. // version 2 pour le reste
  2899. // flusher si on doit lire peu α peu le fichier
  2900. #undef test_flush
  2901. #define test_flush if (opt->flush) { fflush(opt->log); fflush(opt->errlog); }
  2902.  
  2903.  
  2904. // Estimate transfer rate
  2905. // a little bit complex, but not too much
  2906. /*
  2907.   .. : idle
  2908.   ^  : event
  2909.  
  2910.   ----|----|----|----|----|----|----|----|---->
  2911.    1    2    3    4    5    6    7    8    9   time (seconds)
  2912.   ----|----|----|----|----|----|----|----|---->
  2913.   ^........^.........^.........^.........^.... timer 0
  2914.   ----^.........^.........^.........^......... timer 1
  2915.            0    1    0    1    0    1    0     timer N sets its statistics
  2916.       *         *         *         *          timer 0 resync timer 1
  2917.  
  2918.   Therefore, each seconds, we resync the transfer rate with 2-seconds
  2919.  
  2920. */
  2921. int engine_stats(void) {
  2922. #if 0
  2923.   static FILE* debug_fp=NULL;
  2924.   if (!debug_fp)
  2925.     debug_fp=fopen("esstat.txt","wb");
  2926. #endif
  2927.   HTS_STAT.stat_nsocket=HTS_STAT.stat_errors=HTS_STAT.nbk==0;
  2928.   HTS_STAT.nb=0;
  2929.   if (HTS_STAT.HTS_TOTAL_RECV>2048) {
  2930.     TStamp cdif=mtime_local();
  2931.     int i;
  2932.  
  2933.     for(i=0;i<2;i++) {
  2934.       if ( (cdif - HTS_STAT.istat_timestart[i]) >= 2000) {
  2935.         TStamp dif;
  2936. #if 0
  2937. fprintf(debug_fp,"set timer %d\n",i); fflush(debug_fp);
  2938. #endif
  2939.         dif=cdif - HTS_STAT.istat_timestart[i];
  2940.         if ((TStamp)(dif/1000)>0) {
  2941.           LLint byt=(HTS_STAT.HTS_TOTAL_RECV - HTS_STAT.istat_bytes[i]);
  2942.           HTS_STAT.rate=(LLint)((TStamp) ((TStamp)byt/(dif/1000)));
  2943.           HTS_STAT.istat_idlasttimer=i;      // this timer recently sets the stats
  2944.           //
  2945.           HTS_STAT.istat_bytes[i]=HTS_STAT.HTS_TOTAL_RECV;
  2946.           HTS_STAT.istat_timestart[i]=cdif;
  2947.         }
  2948.         return 1;       /* refreshed */
  2949.       }
  2950.     }
  2951.  
  2952.     // resynchronization between timer 0 (master) and 1 (slave)
  2953.     // timer #0 resync timer #1 when reaching 1 second limit
  2954.     if (HTS_STAT.istat_reference01 != HTS_STAT.istat_timestart[0]) {
  2955.       if ( (cdif - HTS_STAT.istat_timestart[0]) >= 1000) {
  2956. #if 0
  2957. fprintf(debug_fp,"resync timer 1\n"); fflush(debug_fp);
  2958. #endif
  2959.         HTS_STAT.istat_bytes[1]=HTS_STAT.HTS_TOTAL_RECV;
  2960.         HTS_STAT.istat_timestart[1]=cdif;
  2961.         HTS_STAT.istat_reference01=HTS_STAT.istat_timestart[0];
  2962.       }
  2963.     }
  2964.  
  2965.   }
  2966.   return 0;
  2967. }
  2968.  
  2969.  
  2970. // bannir host (trop lent etc)
  2971. void host_ban(httrackp* opt,lien_url** liens,int ptr,int lien_tot,lien_back* back,int back_max,char** filters,int filter_max,int* filptr,char* host) {
  2972.   //register int l;
  2973.   register int i;
  2974.  
  2975.   if (host[0]=='!')
  2976.     return;    // erreur.. dΘja cancellΘ.. bizarre.. devrait pas arriver
  2977.  
  2978.   // interdire host
  2979.   if (*filptr < filter_max) {
  2980.     strcpy(filters[*filptr],"-");
  2981.     strcat(filters[*filptr],host);
  2982.     strcat(filters[*filptr],"/*");     // host/ * interdit
  2983.     (*filptr)++; *filptr=minimum(*filptr,filter_max);  
  2984.   }
  2985.   
  2986.   // oups
  2987.   if (strlen(host)<=1) {    // euhh?? longueur <= 1
  2988.     if (strcmp(host,"file://")) {
  2989.       //## if (host[0]!=lOCAL_CHAR) {  // pas local
  2990.       if (opt->log!=NULL) {
  2991.         fprintf(opt->log,"PANIC! HostCancel detected memory leaks [char %d]"LF,host[0]); test_flush;
  2992.       }          
  2993.       return;  // purΘe
  2994.     }
  2995.   }
  2996.   
  2997.   // couper connexion
  2998.   for(i=0;i<back_max;i++) {
  2999.     if (back[i].status>=0)    // rΘception OU prΩt
  3000.       if (strfield2(back[i].url_adr,host)) {
  3001. #if HTS_DEBUG_CLOSESOCK
  3002.         DEBUG_W("host control: deletehttp\n");
  3003. #endif
  3004.         back[i].status=0;  // terminΘ
  3005.         if (back[i].r.soc!=INVALID_SOCKET) deletehttp(&back[i].r);
  3006.         back[i].r.soc=INVALID_SOCKET;
  3007.         back[i].r.statuscode=-2;    // timeout (peu importe si c'est un traffic jam)
  3008.         strcpy(back[i].r.msg,"Link Cancelled by host control");
  3009.         
  3010.         if ((opt->debug>1) && (opt->log!=NULL)) {
  3011.           fprintf(opt->log,"Shutdown: %s%s"LF,back[i].url_adr,back[i].url_fil); test_flush;
  3012.         }          
  3013.       }
  3014.   }
  3015.   
  3016.   // effacer liens
  3017.   //l=strlen(host);
  3018.   for(i=0;i<lien_tot;i++) {
  3019.     //if (liens[i]->adr_len==l) {    // mΩme taille de chaεne
  3020.     // Calcul de taille sΘcurisΘe
  3021.     if (liens[i]) {
  3022.       if (liens[i]->adr) {
  3023.         int l = 0;
  3024.         while((liens[i]->adr[l]) && (l<1020)) l++;
  3025.         if ((l > 0) && (l<1020)) {   // sΘcuritΘ
  3026.           if (strfield2(jump_identification(liens[i]->adr),host)) {    // host
  3027.             if ((opt->debug>1) && (opt->log!=NULL)) {
  3028.               fprintf(opt->log,"Cancel: %s%s"LF,liens[i]->adr,liens[i]->fil); test_flush;
  3029.             }
  3030.             strcpy(liens[i]->adr,"!");    // cancel (invalide hash)
  3031. #if HTS_HASH
  3032. #else
  3033.             liens[i]->sav_len=-1;         // taille invalide
  3034. #endif
  3035.             // on efface pas le hash, because si on rencontre le lien, reverif sav..
  3036.           }
  3037.         } else {
  3038.           if (opt->log!=NULL) {
  3039.             char dmp[1040];
  3040.             dmp[0]='\0';
  3041.             strncat(dmp,liens[i]->adr,1024);
  3042.             fprintf(opt->log,"WARNING! HostCancel detected memory leaks [len %d at %d]"LF,l,i); test_flush;
  3043.             fprintf(opt->log,"dump 1024 bytes (address %d): "LF"%s"LF,(int)liens[i]->adr,dmp); test_flush;
  3044.           }          
  3045.         }
  3046.       } else {
  3047.         if (opt->log!=NULL) {
  3048.           fprintf(opt->log,"WARNING! HostCancel detected memory leaks [adr at %d]"LF,i); test_flush;
  3049.         }  
  3050.       }
  3051.     } else {
  3052.       if (opt->log!=NULL) {
  3053.         fprintf(opt->log,"WARNING! HostCancel detected memory leaks [null at %d]"LF,i); test_flush;
  3054.       }  
  3055.     }
  3056.     //}
  3057.   }
  3058. }
  3059.  
  3060.  
  3061. /* Init structure */
  3062. /* 1 : init */
  3063. /* -1 : off */
  3064. char* structcheck_init(int init) {
  3065.   static char* structcheck_buff=NULL;
  3066.   if (init) {
  3067.     if (structcheck_buff)
  3068.       freet(structcheck_buff);
  3069.     structcheck_buff=NULL;
  3070.   }
  3071.   if (init != -1) {
  3072.     if (structcheck_buff==NULL) {
  3073.       structcheck_buff=(char*) malloct(65536);  // dΘsallouΘ xh_xx
  3074.       if (structcheck_buff)
  3075.         strcpy(structcheck_buff,"#");
  3076.     }
  3077.   }
  3078.   return structcheck_buff;
  3079. }
  3080.  
  3081.  
  3082.  
  3083. // vΘrifier prΘsence de l'arbo
  3084. int structcheck(char* s) {
  3085.   // vΘrifier la prΘsence des dossier(s)
  3086.   char *a=s;
  3087.   char nom[HTS_URLMAXSIZE*2];
  3088.   char *b;
  3089.   char* structcheck_buff=NULL;
  3090.   if (strnotempty(s)==0) return 0;
  3091.   if (strlen(s)>HTS_URLMAXSIZE) return 0;
  3092.  
  3093.   // Get buffer address
  3094.   structcheck_buff=structcheck_init(0);
  3095.   if (!structcheck_buff)
  3096.     return -1;
  3097.  
  3098.   if (strlen(structcheck_buff)>65000) {
  3099.     strcpy(structcheck_buff,"#");  // rΘinit.. c'est idiot ** **
  3100.   }
  3101.   
  3102.   if (structcheck_buff) {
  3103.     b=nom;
  3104.     do {    
  3105.       if (*a) *b++=*a++;
  3106.       while((*a!='/') && (*a!='\0')) *b++=*a++;
  3107.       *b='\0';    // pas de ++ pour boucler
  3108.       if (*a=='/') {    // toujours dossier
  3109.         if (strnotempty(nom)) {
  3110.           char tempo[HTS_URLMAXSIZE*2];
  3111.           
  3112.           strcpy(tempo,"#"); strcat(tempo,nom); strcat(tempo,"#");
  3113.           if (strstr(structcheck_buff,tempo)==NULL) {    // non encore crΘΘ
  3114.             strcat(structcheck_buff,"#"); strcat(structcheck_buff,nom); strcat(structcheck_buff,"#");  // ajouter α la liste
  3115.                         
  3116. #if HTS_WIN
  3117.             if (mkdir(fconv(nom))!=0)
  3118. #else    
  3119.               if (mkdir(fconv(nom),HTS_ACCESS_FOLDER)!=0)
  3120. #endif
  3121.               {
  3122. #if HTS_REMOVE_ANNOYING_INDEX
  3123.                 // might be a filename with same name than this folder
  3124.                 // then, remove it to allow folder creation
  3125.                 // it happends when servers gives a folder index while
  3126.                 // requesting / page
  3127.                 // -> if the file can be opened (not a folder) then rename it
  3128.                 FILE* fp=fopen(fconv(nom),"ab");
  3129.                 if (fp) {
  3130.                   fclose(fp);
  3131.                   rename(fconv(nom),fconcat(fconv(nom),".txt"));
  3132.                 }
  3133.                 // if it fails, that's too bad
  3134. #if HTS_WIN
  3135.                 mkdir(fconv(nom));
  3136. #else    
  3137.                 mkdir(fconv(nom),HTS_ACCESS_FOLDER);
  3138. #endif
  3139. #endif
  3140.                 // Si existe dΘja renvoie une erreur.. tant pis
  3141.               }
  3142. #if HTS_WIN==0
  3143.               chmod(fconv(nom),HTS_ACCESS_FOLDER);
  3144. #endif
  3145.           }
  3146.         }
  3147.         *b++=*a++;    // slash
  3148.       } 
  3149.     } while(*a);
  3150.   }
  3151.   return 0;
  3152. }
  3153.  
  3154.  
  3155. // sauver un fichier
  3156. int filesave(char* adr,int len,char* s) {
  3157.   FILE* fp;
  3158.   // Θcrire le fichier
  3159.   if ((fp=filecreate(s))!=NULL) {
  3160.     int nl=0;
  3161.     if (len>0) {
  3162.       nl=(int) fwrite(adr,1,len,fp);
  3163.     }
  3164.     fclose(fp);
  3165.     usercommand(0,NULL,antislash(s));
  3166.     if (nl!=len)  // erreur
  3167.       return -1;
  3168.   } else
  3169.     return -1;
  3170.   
  3171.   return 0;
  3172. }
  3173.  
  3174.  
  3175. // ouvrir un fichier (avec chemin Un*x)
  3176. FILE* filecreate(char* s) {
  3177.   char fname[HTS_URLMAXSIZE*2];
  3178.   FILE* fp;
  3179.   fname[0]='\0';
  3180.  
  3181.   // noter lst
  3182.   filenote(s,NULL);
  3183.   
  3184.   // if (*s=='/') strcpy(fname,s+1); else strcpy(fname,s);    // pas de / (root!!) // ** SIIIIIII!!! α cause de -O <path>
  3185.   strcpy(fname,s);
  3186.  
  3187. #if HTS_DOSNAME
  3188.   // remplacer / par des slash arriΦre
  3189.   {
  3190.     int i=0;
  3191.     while(fname[i]) {
  3192.       if (fname[i]=='/')
  3193.         fname[i]='\\';
  3194.       i++;
  3195.     } 
  3196.   } 
  3197.   // a partir d'ici le slash devient antislash
  3198. #endif
  3199.   
  3200.   // construite le chemin si besoin est
  3201.   if (structcheck(s)!=0) {
  3202.     return NULL;
  3203.   }
  3204.   
  3205.   
  3206.   // ouvrir
  3207.   fp=fopen(fname,"wb");
  3208. #if HTS_WIN==0
  3209.   if (fp!=NULL) chmod(fname,HTS_ACCESS_FILE);
  3210. #endif
  3211.   return fp;
  3212. }
  3213.  
  3214. // noter fichier
  3215. int filenote(char* s,filecreate_params* params) {
  3216. //int filenote(char* s,char* params) {
  3217.   static FILE* lst = NULL;
  3218.   static char path[HTS_URLMAXSIZE*2]="";
  3219.   
  3220.   // gestion du fichier liste liste
  3221.   if (params) {
  3222.     //filecreate_params* p = (filecreate_params*) params;
  3223.     strcpy(path,params->path);
  3224.     lst=params->lst;
  3225.     return 0;
  3226.   } else if (lst) {
  3227.     char savelst[HTS_URLMAXSIZE*2];
  3228.     strcpy(savelst,fslash(s));
  3229.     // couper chemin?
  3230.     if (strnotempty(path)) {
  3231.       if (strncmp(fslash(path),savelst,strlen(path))==0) {  // couper
  3232.         strcpy(savelst,s+strlen(path));
  3233.       }
  3234.     }
  3235.     fprintf(lst,"[%s]"LF,savelst);
  3236.     fflush(lst);
  3237.   }
  3238.   return 1;
  3239. }
  3240.  
  3241. // executer commande utilisateur
  3242. HTS_INLINE void usercommand(int _exe,char* _cmd,char* file) {
  3243.   static int exe=0;
  3244.   static char cmd[2048]="";
  3245.  
  3246.   if (_exe) {
  3247.     strcpy(cmd,_cmd);
  3248.     if (strnotempty(cmd))
  3249.       exe=_exe;
  3250.     else
  3251.       exe=0;
  3252.   }
  3253.  
  3254. #if HTS_ANALYSTE
  3255.   if (hts_htmlcheck_filesave)
  3256.   if (strnotempty(file))
  3257.     hts_htmlcheck_filesave(file);
  3258. #endif
  3259.  
  3260.   if (exe) {
  3261.     if (strnotempty(file)) {
  3262.       if (strnotempty(cmd)) {
  3263.         usercommand_exe(cmd,file);
  3264.       }
  3265.     }
  3266.   }
  3267. }
  3268. void usercommand_exe(char* cmd,char* file) {
  3269.   char temp[8192];
  3270.   char c[2]="";
  3271.   int i;
  3272.   temp[0]='\0';
  3273.   //
  3274.   for(i=0;i<(int) strlen(cmd);i++) {
  3275.     if ((cmd[i]=='$') && (cmd[i+1]=='0')) {
  3276.       strcat(temp,file);
  3277.       i++;
  3278.     } else {
  3279.       c[0]=cmd[i]; c[1]='\0';
  3280.       strcat(temp,c);
  3281.     }
  3282.   }
  3283.   system(temp);
  3284. }
  3285.  
  3286. // Θcrire n espaces dans fp
  3287. HTS_INLINE int fspc(FILE* fp,char* type) {
  3288.   static int error=0,warning=0,info=0;
  3289.   //
  3290.   if (fp) {
  3291.     char s[256];
  3292.     time_t tt;
  3293.     struct tm* A;
  3294.     tt=time(NULL);
  3295.     A=localtime(&tt);
  3296.     strftime(s,250,"%H:%M:%S",A);
  3297.     if (strnotempty(type))
  3298.       fprintf(fp,"%s\t%c%s: \t",s,hichar(*type),type+1);
  3299.     else
  3300.       fprintf(fp,"%s\t \t",s);
  3301.     if (strcmp(type,"warning")==0)
  3302.       warning++;
  3303.     else if (strcmp(type,"error")==0)
  3304.       error++;
  3305.     else if (strcmp(type,"info")==0)
  3306.       info++;
  3307.   } 
  3308.   else if (!type)
  3309.     error=warning=info=0;     // reset
  3310.   else if (strcmp(type,"warning")==0)
  3311.     return warning;
  3312.   else if (strcmp(type,"error")==0)
  3313.     return error;
  3314.   else if (strcmp(type,"info")==0)
  3315.     return info;
  3316.   return 0;
  3317. }
  3318.  
  3319.  
  3320. // vΘrifier taux de transfert
  3321. #if 0
  3322. void check_rate(TStamp stat_timestart,int maxrate) {
  3323.   // vΘrifier taux de transfert (pas trop grand?)
  3324.   /*
  3325.   if (maxrate>0) {
  3326.     int r = (int) (HTS_STAT.HTS_TOTAL_RECV/(time_local()-stat_timestart));    // taux actuel de transfert
  3327.     HTS_STAT.HTS_TOTAL_RECV_STATE=0;
  3328.     if (r>maxrate) {    // taux>taux autorisΘ
  3329.       int taux = (int) (((TStamp) (r - maxrate) * 100) / (TStamp) maxrate);
  3330.       if (taux<15)
  3331.         HTS_STAT.HTS_TOTAL_RECV_STATE=1;   // ralentir un peu (<15% dΘpassement)
  3332.       else if (taux<50)
  3333.         HTS_STAT.HTS_TOTAL_RECV_STATE=2;   // beaucoup (<50% dΘpassement)
  3334.       else
  3335.         HTS_STAT.HTS_TOTAL_RECV_STATE=3;   // ΘnormΘment (>50% dΘpassement)
  3336.     }
  3337.   }
  3338.   */
  3339. }
  3340. #endif
  3341.  
  3342. // ---
  3343. // sous routines liΘes au moteur et au backing
  3344.  
  3345. // supplemental links ready (done) after ptr
  3346. int backlinks_done(lien_url** liens,int lien_tot,int ptr) {
  3347.   int n=0;
  3348.   int i;
  3349.   //Links done and stored in cache
  3350.   for(i=ptr+1;i<lien_tot;i++) {
  3351.     if (liens[i]) {
  3352.       if (liens[i]->pass2 == -1) {
  3353.         n++;
  3354.       }
  3355.     }
  3356.   }
  3357.   return n;
  3358. }
  3359.  
  3360. // remplir backing si moins de max_bytes en mΘmoire
  3361. HTS_INLINE int back_fillmax(lien_back* back,int back_max,httrackp* opt,cache_back* cache,lien_url** liens,int ptr,int numero_passe,int lien_tot) {
  3362.   if (!opt->state.stop) {
  3363.     if (back_incache(back,back_max)<opt->maxcache) {  // pas trop en mΘmoire?
  3364.       return back_fill(back,back_max,opt,cache,liens,ptr,numero_passe,lien_tot);
  3365.     }
  3366.   }
  3367.   return -1;                /* plus de place */
  3368. }
  3369.  
  3370. // remplir backing
  3371. int back_fill(lien_back* back,int back_max,httrackp* opt,cache_back* cache,lien_url** liens,int ptr,int numero_passe,int lien_tot) {
  3372.   int n;
  3373.  
  3374.   // ajouter autant de socket qu'on peut ajouter
  3375.   n=opt->maxsoc-back_nsoc(back,back_max);
  3376.  
  3377.   // vΘrifier qu'il restera assez de place pour les tests ensuite (en thΘorie, 1 entrΘe libre restante suffirait)
  3378.   n=min( n, back_available(back,back_max) - 8 );
  3379.  
  3380.   // no space left on backing stack - do not back anymore
  3381.   if (back_stack_available(back,back_max) <= 2)
  3382.     n=0;
  3383.  
  3384.   if (n>0) {
  3385.     int p;
  3386.  
  3387.     if (ptr<cache->ptr_last) {      /* restart (2 scans: first html, then non html) */
  3388.       cache->ptr_ant=0;
  3389.     }
  3390.  
  3391.     p=ptr+1;
  3392.     /* on a dΘja parcouru */
  3393.     if (p<cache->ptr_ant)
  3394.       p=cache->ptr_ant;
  3395.     while( (p<lien_tot) && (n>0) ) {
  3396.     //while((p<lien_tot) && (n>0) && (p < ptr+opt->maxcache_anticipate)) {
  3397.       int ok=1;
  3398.       
  3399.       // on ne met pas le fichier en backing si il doit Ωtre traitΘ aprΦs
  3400.       if (liens[p]->pass2) {  // 2Φ passe
  3401.         if (numero_passe!=1)
  3402.           ok=0;
  3403.       } else {
  3404.         if (numero_passe!=0)
  3405.           ok=0;
  3406.       }
  3407.       
  3408.       // note: si un backing est fini, il reste en mΘmoire jusqu'α ce que
  3409.       // le ptr l'atteigne
  3410.       if (ok) {
  3411.         if (!back_exist(back,back_max,liens[p]->adr,liens[p]->fil,liens[p]->sav)) {
  3412.           if (back_add(back,back_max,opt,cache,liens[p]->adr,liens[p]->fil,liens[p]->sav,liens[liens[p]->precedent]->adr,liens[liens[p]->precedent]->fil,liens[p]->testmode,&liens[p]->pass2)==-1) {
  3413.             if ( (opt->debug>1) && (opt->errlog!=NULL) ) {
  3414.               fspc(opt->errlog,"debug"); fprintf(opt->errlog,"error: unable to add more links through back_add for back_fill"LF);
  3415.               test_flush;
  3416.             }                    
  3417. #if BDEBUG==1
  3418.             printf("error while adding\n");
  3419. #endif                  
  3420.             n=0;    // sortir
  3421.           } else {
  3422.             n--;
  3423. #if BDEBUG==1
  3424.             printf("backing: %s%s\n",liens[p]->adr,liens[p]->fil);          
  3425. #endif
  3426.           } 
  3427.         }
  3428.       }
  3429.       p++;
  3430.     }  // while
  3431.     /* sauver position derniΦre anticipation */
  3432.     cache->ptr_ant=p;
  3433.     cache->ptr_last=ptr;
  3434.   }
  3435.   return 0;
  3436. }
  3437. // ---
  3438.  
  3439.  
  3440.  
  3441.  
  3442.  
  3443.  
  3444.  
  3445.  
  3446.  
  3447.  
  3448.  
  3449.  
  3450.  
  3451.  
  3452.  
  3453.  
  3454.  
  3455.  
  3456. // routines de dΘtournement de SIGHUP & co (Unix)
  3457. //
  3458. httrackp* hts_declareoptbuffer(httrackp* optdecl) {
  3459.   static httrackp* opt=NULL;
  3460.   if (optdecl) opt=optdecl;
  3461.   return opt;
  3462. }
  3463. //
  3464. void sig_finish( int code ) {       // finir et quitter
  3465.   signal(code,sig_term);  // quitter si encore
  3466.   exit_xh=1;
  3467.   printf("\nExit requested to engine (signal %d)\n",code);
  3468. }
  3469. void sig_term( int code ) {       // quitter brutalement
  3470.   printf("\nProgram terminated (signal %d)\n",code);
  3471.   exit(0);
  3472. }
  3473. #if HTS_WIN
  3474. void sig_ask( int code ) {        // demander
  3475.   static char s[256];
  3476.   signal(code,sig_term);  // quitter si encore
  3477.   printf("\nQuit program/Interrupt/Cancel? (Q/I/C) ");
  3478.   fflush(stdout);
  3479.   scanf("%s",s);
  3480.   if ( (s[0]=='y') || (s[0]=='Y') || (s[0]=='o') || (s[0]=='O') || (s[0]=='q') || (s[0]=='Q'))
  3481.     exit(0);     // quitter
  3482.   else if ( (s[0]=='i') || (s[0]=='I') ) {
  3483.     httrackp* opt=hts_declareoptbuffer(NULL);
  3484.     if (opt) {
  3485.       // ask for stop
  3486.       opt->state.stop=1;
  3487.     }
  3488.   }
  3489.   signal(code,sig_ask);  // remettre signal
  3490. }
  3491. #else
  3492. void sig_back( int code ) {       // ignorer et mettre en backing 
  3493.   signal(code,sig_ignore);
  3494.   sig_doback(0);
  3495. }
  3496. void sig_ask( int code ) {        // demander
  3497.   static char s[256];
  3498.   signal(code,sig_term);  // quitter si encore
  3499.   printf("\nQuit program/Interrupt/Background/bLind background/Cancel? (Q/I/B/L/C) ");
  3500.   fflush(stdout);
  3501.   scanf("%s",s);
  3502.   if ( (s[0]=='y') || (s[0]=='Y') || (s[0]=='o') || (s[0]=='O') || (s[0]=='q') || (s[0]=='Q'))
  3503.     exit(0);     // quitter
  3504.   else if ( (s[0]=='b') || (s[0]=='B') || (s[0]=='a') || (s[0]=='A') )
  3505.     sig_doback(0);  // arriΦre plan
  3506.   else if ( (s[0]=='l') || (s[0]=='L') )
  3507.     sig_doback(1);  // arriΦre plan
  3508.   else if ( (s[0]=='i') || (s[0]=='I') ) {
  3509.     httrackp* opt=hts_declareoptbuffer(NULL);
  3510.     if (opt) {
  3511.       // ask for stop
  3512.       opt->state.stop=1;
  3513.     }
  3514.     signal(code,sig_ask);  // remettre signal
  3515.   }
  3516.   else {
  3517.     printf("cancel..\n");
  3518.     signal(code,sig_ask);  // remettre signal
  3519.   }
  3520. }
  3521. void sig_ignore( int code ) {     // ignorer signal
  3522.   // // signal(code,sig_ignore);
  3523. }
  3524. void sig_doback(int blind) {       // mettre en backing 
  3525.   int out=-1;
  3526.   //
  3527.   printf("\nMoving to background to complete the mirror...\n"); fflush(stdout);
  3528.  
  3529.   {
  3530.     httrackp* opt=hts_declareoptbuffer(NULL);
  3531.     if (opt) {
  3532.       // suppress logging and asking lousy questions
  3533.       opt->quiet=1;
  3534.       opt->verbosedisplay=0;
  3535.     }
  3536.   }
  3537.  
  3538.   if (!blind)
  3539.     out = open("hts-nohup.out",O_CREAT|O_WRONLY,S_IRUSR|S_IWUSR);
  3540.   if (out == -1)
  3541.     out = open("/dev/null",O_WRONLY,S_IRUSR|S_IWUSR);
  3542.   close(0);
  3543.   close(1);
  3544.   dup(out);
  3545.   close(2);
  3546.   dup(out);
  3547.   //
  3548.   switch (fork()) {
  3549.   case 0: 
  3550.     break;
  3551.   case -1:
  3552.     printf("Error: can not fork process\n");
  3553.     break;
  3554.   default:            // pere
  3555.     usleep(100000);   // pause 1/10s "A  microsecond  is  .000001s"
  3556.     _exit(0);
  3557.     break;  
  3558.   }
  3559. }
  3560. #endif
  3561. // fin routines de dΘtournement de SIGHUP & co
  3562.  
  3563. // Poll stdin.. si besoin
  3564. #if HTS_POLL
  3565. // lecture stdin des caractΦres disponibles
  3566. int read_stdin(char* s,int max) {
  3567.   int i=0;
  3568.   while((check_stdin()) && (i<(max-1)) )
  3569.     s[i++]=fgetc(stdin);
  3570.   s[i]='\0';
  3571.   return i;
  3572. }
  3573. #ifdef _WIN32
  3574. HTS_INLINE int check_stdin(void) {
  3575.   return (_kbhit());
  3576. }
  3577. #else
  3578. HTS_INLINE int check_flot(T_SOC s) {
  3579.   fd_set fds;
  3580.   struct timeval tv;
  3581.   FD_ZERO(&fds);
  3582.   FD_SET((T_SOC) s,&fds);
  3583.   tv.tv_sec=0;
  3584.   tv.tv_usec=0;
  3585.   select(s+1,&fds,NULL,NULL,&tv);
  3586.   return FD_ISSET(s,&fds);
  3587. }
  3588. HTS_INLINE int check_stdin(void) {
  3589.   fflush(stdout); fflush(stdin);
  3590.   if (check_flot(0))
  3591.     return 1;
  3592.   return 0;
  3593. }
  3594. #endif
  3595. #endif
  3596.  
  3597. // Attente de touche
  3598. #if HTS_ANALYSTE
  3599. int ask_continue(void) {
  3600.   char* s;
  3601.   s=hts_htmlcheck_query2(HTbuff);
  3602.   if (s) {
  3603.     if (strnotempty(s)) {
  3604.       if ((strfield2(s,"N")) || (strfield2(s,"NO")) || (strfield2(s,"NON")))
  3605.         return 0;
  3606.     }
  3607.     return 1;
  3608.   }
  3609.   return 1;
  3610. }
  3611. #else
  3612. int ask_continue(void) {
  3613.   char s[12]="";
  3614.   printf("Press <Y><Enter> to confirm, <N><Enter> to abort\n");
  3615.   io_flush; linput(stdin,s,4);
  3616.   if (strnotempty(s)) {
  3617.     if ((strfield2(s,"N")) || (strfield2(s,"NO")) || (strfield2(s,"NON")))
  3618.       return 0;
  3619.   }
  3620.   return 1;
  3621. }
  3622. #endif
  3623.  
  3624. // nombre de digits dans un nombre
  3625. int nombre_digit(int n) {
  3626.   register int i=1;
  3627.   while(n >= 10) { n/=10; i++; }
  3628.   return i;
  3629. }
  3630.  
  3631.  
  3632. // renvoi adresse de la fin du token dans p
  3633. // renvoi NULL si la chaine est un token unique
  3634. // (PATCHE Θgalement la chaine)
  3635. // ex: "test" "test2" renvoi adresse sur espace
  3636. // flag==1 si chaine comporte des echappements comme \"
  3637. char* next_token(char* p,int flag) {
  3638.   int detect=0;
  3639.   int quote=0;
  3640.   p--;
  3641.   do {
  3642.     p++;
  3643.     if (flag && (*p=='\\')) {   // sauter \x ou \"
  3644.       if (quote) {
  3645.         char c='\0';
  3646.         if (*(p+1)=='\\')
  3647.           c='\\';
  3648.         else if (*(p+1)=='"')
  3649.           c='"';
  3650.         if (c) {
  3651.           char tempo[8192];
  3652.           tempo[0]=c; tempo[1]='\0';
  3653.           strcat(tempo,p+2);
  3654.           strcpy(p,tempo);
  3655.         }
  3656.       }
  3657.     }
  3658.     else if (*p==34) {  // guillemets (de fin)
  3659.       quote=!quote;
  3660.     }
  3661.     else if (*p==32) {
  3662.       if (!quote)
  3663.         detect=1;
  3664.     }
  3665.     else if (*p=='\0') {
  3666.       p=NULL;
  3667.       detect=1;
  3668.     }
  3669.   } while(!detect);
  3670.   return p;
  3671. }
  3672.  
  3673. // routines annexes 
  3674. #if HTS_ANALYSTE
  3675. // canceller un fichier (noter comme cancellable)
  3676. char* hts_cancel_file(char * s) {
  3677.   static char sav[HTS_URLMAXSIZE*2]="";
  3678.   if (s[0]!='\0')
  3679.   if (sav[0]=='\0')
  3680.     strcpy(sav,s);
  3681.   return sav;
  3682. }
  3683. void hts_cancel_test(void) {
  3684.   if (_hts_in_html_parsing==2)
  3685.     _hts_cancel=2;
  3686. }
  3687. void hts_cancel_parsing(void) {
  3688.   if (_hts_in_html_parsing)
  3689.    _hts_cancel=1;
  3690. }
  3691. #endif
  3692. //        for(_i=0;(_i<back_max) && (index<NStatsBuffer);_i++) {
  3693. //          i=(back_index+_i)%back_max;    // commencer par le "premier" (l'actuel)
  3694. //          if (back[i].status>=0) {     // signifie "lien actif"
  3695.  
  3696.  
  3697. /*  
  3698. hts_add_file, add/get elements in the add chain for java parsing
  3699. if file_position >= 0
  3700.   push 'file/file_position'
  3701.   return 1 (return 0 if exists)
  3702. else
  3703.   pop file -> 'file'
  3704.   return 'file_position'
  3705. else if empty/error
  3706.   return -1;
  3707. */
  3708. typedef struct addfile_chain {
  3709.   char name[1024];
  3710.   int pos;
  3711.   struct addfile_chain* next;
  3712. } addfile_chain;
  3713. int hts_add_file(char* file,int file_position) {
  3714.   static struct addfile_chain* chain=NULL;
  3715.  
  3716.   if (file_position>=0) {         /* copy file to the chain */
  3717.     struct addfile_chain** current;
  3718.     current=&chain;                     /* start from */
  3719.     while(*current) {
  3720.       if (strcmp((*current)->name,file)==0)
  3721.         return 0;                       /* already exists */
  3722.       current=&( (*current)->next );    /* 'next' address */
  3723.     }
  3724.     *current=calloct(1,sizeof(addfile_chain));
  3725.     if (*current) {
  3726.       (*current)->next=NULL;
  3727.       (*current)->pos=-1;
  3728.       (*current)->name[0]='\0';
  3729.     }
  3730.     if (*current) {
  3731.       strcpy((*current)->name,file);
  3732.       (*current)->pos=file_position;
  3733.       return 1;
  3734.     } else {
  3735.       printf("PANIC! Too many Java files during parsing [1]\n");
  3736.       return -1;
  3737.     }
  3738.   } else {                      /* copy last element in file and delete it */
  3739.     if (file)
  3740.       file[0]='\0';
  3741.     if (chain) {
  3742.       struct addfile_chain** current;
  3743.       int pos=-1;
  3744.       current=&chain;                     /* start from */
  3745.       while( (*current)->next ) {
  3746.         current=&( (*current)->next );    /* 'next' address */
  3747.       }
  3748.       if (file)
  3749.         strcpy(file,(*current)->name);
  3750.       pos=(*current)->pos;
  3751.       freet(*current);
  3752.       *current=NULL;
  3753.       return pos;
  3754.     }
  3755.     return -1;                            /* no more elements */
  3756.   }
  3757.  
  3758.   return 0;
  3759. }
  3760.  
  3761. #if HTS_ANALYSTE
  3762. // en train de parser un fichier html? rΘponse: % effectuΘs
  3763. // flag>0 : refresh demandΘ
  3764. int hts_is_parsing(int flag) {
  3765.   if (_hts_in_html_parsing) {  // parsing?
  3766.     if (flag>=0) _hts_in_html_poll=1;  // faudrait un tit refresh
  3767.     return max(_hts_in_html_done,1); // % effectuΘs
  3768.   } else {
  3769.     return 0;                 // non
  3770.   }
  3771. }
  3772. int hts_is_testing(void) {            // 0 non 1 test 2 purge
  3773.   if (_hts_in_html_parsing==2)
  3774.     return 1;
  3775.   else if (_hts_in_html_parsing==3)
  3776.     return 2;
  3777.   return 0;
  3778. }
  3779. // message d'erreur?
  3780. char* hts_errmsg(void) {
  3781.   return _hts_errmsg;
  3782. }
  3783. // mode pause transfer
  3784. int hts_setpause(int p) {
  3785.   if (p>=0) _hts_setpause=p;
  3786.   return _hts_setpause;
  3787. }
  3788. // ask for termination
  3789. int hts_request_stop(int force) {
  3790.   httrackp* opt=hts_declareoptbuffer(NULL);
  3791.   if (opt) {
  3792.     opt->state.stop=1;
  3793.   }
  3794.   return 0;
  3795. }
  3796. // rΘgler en cours de route les paramΦtres rΘglables..
  3797. // -1 : erreur
  3798. int hts_setopt(httrackp* set_opt) {
  3799.   if (set_opt) {
  3800.     httrackp* engine_opt=hts_declareoptbuffer(NULL);
  3801.     if (engine_opt) {
  3802.       //_hts_setopt=opt;
  3803.       copy_htsopt(set_opt,engine_opt);
  3804.     }
  3805.   }
  3806.   return 0;
  3807. }
  3808. // ajout d'URL
  3809. // -1 : erreur
  3810. int hts_addurl(char** url) {
  3811.   if (url) _hts_addurl=url;
  3812.   return (_hts_addurl!=NULL);
  3813. }
  3814. int hts_resetaddurl(void) {
  3815.   _hts_addurl=NULL;
  3816.   return (_hts_addurl!=NULL);
  3817. }
  3818. // copier nouveaux paramΦtres si besoin
  3819. int copy_htsopt(httrackp* from,httrackp* to) {
  3820.   if (from->maxsite > -1) 
  3821.     to->maxsite = from->maxsite;
  3822.   
  3823.   if (from->maxfile_nonhtml > -1) 
  3824.     to->maxfile_nonhtml = from->maxfile_nonhtml;
  3825.   
  3826.   if (from->maxfile_html > -1) 
  3827.     to->maxfile_html = from->maxfile_html;
  3828.   
  3829.   if (from->maxsoc > 0) 
  3830.     to->maxsoc = from->maxsoc;
  3831.   
  3832.   if (from->nearlink > -1) 
  3833.     to->nearlink = from->nearlink;
  3834.   
  3835.   if (from->timeout > -1) 
  3836.     to->timeout = from->timeout;
  3837.   
  3838.   if (from->rateout > -1)
  3839.     to->rateout = from->rateout;
  3840.   
  3841.   if (from->maxtime > -1) 
  3842.     to->maxtime = from->maxtime;
  3843.   
  3844.   if (from->maxrate > -1)
  3845.     to->maxrate = from->maxrate;
  3846.   
  3847.   if (strnotempty(from->user_agent)) 
  3848.     strcpy(to->user_agent , from->user_agent);
  3849.   
  3850.   if (from->retry > -1) 
  3851.     to->retry = from->retry;
  3852.   
  3853.   if (from->hostcontrol > -1) 
  3854.     to->hostcontrol = from->hostcontrol;
  3855.   
  3856.   if (from->errpage > -1) 
  3857.     to->errpage = from->errpage;
  3858.  
  3859.   if (from->parseall > -1) 
  3860.     to->parseall = from->parseall;
  3861.  
  3862.  
  3863.   // test all: bit 8 de travel
  3864.   if (from->travel > -1)  {
  3865.     if (from->travel & 256)
  3866.       to->travel|=256;
  3867.     else
  3868.       to->travel&=255;
  3869.   }
  3870.  
  3871.  
  3872.   return 0;
  3873. }
  3874.  
  3875. #endif
  3876. //
  3877.  
  3878.  
  3879.  
  3880.  
  3881.  
  3882. // message copyright interne
  3883. void voidf(void) {
  3884.   char* a;
  3885.   a=""CRLF""CRLF;
  3886.   a="+-----------------------------------------------+"CRLF;
  3887.   a="|HyperTextTRACKer, Offline Browser Utility      |"CRLF;
  3888.   a="|                      HTTrack Website Copier   |"CRLF;
  3889.   a="|Code:         Windows Interface Xavier Roche   |"CRLF;
  3890.   a="|                    HTS/HTTrack Xavier Roche   |"CRLF;
  3891.   a="|                .class Parser Yann Philippot   |"CRLF;
  3892.   a="|                                               |"CRLF;
  3893.   a="|Tested on:                 Windows95,98,NT,2K  |"CRLF;
  3894.   a="|                           Linux PC            |"CRLF;
  3895.   a="|                           Sun-Solaris 5.6     |"CRLF;
  3896.   a="|                           AIX 4               |"CRLF;
  3897.   a="|                                               |"CRLF;
  3898.   a="|Copyright (C) Xavier Roche and other           |"CRLF;
  3899.   a="|contributors                                   |"CRLF;
  3900.   a="|                                               |"CRLF;
  3901.   a="|Use this program at your own risks!            |"CRLF;    
  3902.   a="+-----------------------------------------------+"CRLF;
  3903.   a=""CRLF;
  3904. }
  3905.  
  3906.  
  3907. // HTTrack Website Copier Copyright (C) Xavier Roche and other contributors
  3908. //
  3909.  
  3910.